home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-28  |  152.5 KB  |  5,188 lines

  1. /* Window creation, deletion and examination for XEmacs.
  2.    Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
  3.    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
  4.  
  5. This file is part of XEmacs.
  6.  
  7. XEmacs is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with XEmacs; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Synched up with: FSF 19.28, except for `display-buffer'. */
  22. /* Beginning to diverge significantly. */
  23.  
  24. /* This file has been Mule-ized. */
  25.  
  26. #include <config.h>
  27. #include "lisp.h"
  28.  
  29. #include "buffer.h"
  30. #include "device.h"
  31. #include "faces.h"
  32. #include "frame.h"
  33. #include "glyphs.h"
  34. #include "redisplay.h"
  35. #include "window.h"
  36. #include "commands.h"
  37.  
  38. Lisp_Object Qwindowp, Qwindow_live_p;
  39. Lisp_Object Qwindow_configurationp;
  40. Lisp_Object Qscroll_up;
  41. Lisp_Object Qscroll_down;
  42. Lisp_Object Qvisible;
  43.  
  44. static int window_pixel_width_to_char_width (struct window *w,
  45.                          int pixel_width,
  46.                          int include_margins_p);
  47. static int window_char_width_to_pixel_width (struct window *w,
  48.                          int char_width,
  49.                          int include_margins_p);
  50. static int window_pixel_height_to_char_height (struct window *w,
  51.                            int pixel_height,
  52.                            int include_modeline_p);
  53. static int window_char_height_to_pixel_height (struct window *w,
  54.                            int char_height,
  55.                            int include_modeline_p);
  56.  
  57. #ifdef ENERGIZE
  58. extern void energize_buffer_shown_hook ();
  59. extern void energize_buffer_hidden_hook ();
  60. extern void energize_window_selected_hook ();
  61. extern void energize_window_deselected_hook ();
  62. extern Lisp_Object desired_psheet_buffer ();
  63. extern void make_psheets_desired ();
  64. #endif
  65.  
  66. /* Thickness of shadow border around 3d modelines. */
  67. Lisp_Object Vmodeline_shadow_thickness;
  68.  
  69. /* Whether a modeline should be displayed. */
  70. Lisp_Object Vhas_modeline_p;
  71.  
  72. /* Scroll if point lands on the bottom line and that line is partially
  73.    clipped. */
  74. int scroll_on_clipped_lines;
  75.  
  76. /* The minibuffer window of the selected frame.
  77.    Note that you cannot test for minibufferness of an arbitrary window
  78.    by comparing against this; but you can test for minibufferness of
  79.    the selected window.  */
  80. Lisp_Object minibuf_window;
  81.  
  82. /* Non-nil means it is the window for C-M-v to scroll
  83.    when the minibuffer is selected.  */
  84. Lisp_Object Vminibuf_scroll_window;
  85.  
  86. /* Non-nil means this is the buffer whose window C-M-v should scroll.  */
  87. Lisp_Object Vother_window_scroll_buffer;
  88.  
  89. /* Non-nil means it's function to call to display temp buffers.  */
  90. Lisp_Object Vtemp_buffer_show_function;
  91.  
  92. /* If a window gets smaller than either of these, it is removed. */
  93. int window_min_height;
  94. int window_min_width;
  95.  
  96. /* Nonzero implies Fdisplay_buffer should create windows. */
  97. int pop_up_windows;
  98.  
  99. #if 0 /* FSFmacs */
  100. /* Nonzero implies make new frames for Fdisplay_buffer.  */
  101. int pop_up_frames;
  102.  
  103. /* Non-nil means use this function instead of default */
  104. Lisp_Object Vpop_up_frame_function;
  105. #endif
  106.  
  107. /* Function to call *instead of* Fdisplay_buffer.  */
  108. Lisp_Object Vdisplay_buffer_function;
  109.  
  110. /* Function to call as the first thing that Fdisplay_buffer does (can be
  111.    used to select an appropriate frame, for example).  */
  112. Lisp_Object Vpre_display_buffer_function;
  113.  
  114. #if 0 /* FSFmacs */
  115. /* List of buffer *names* for buffers that should have their own frames.  */
  116. Lisp_Object Vspecial_display_buffer_names;
  117.  
  118. /* List of regexps for buffer names that should have their own frames.  */
  119. Lisp_Object Vspecial_display_regexps;
  120.  
  121. /* Function to pop up a special frame.  */
  122. Lisp_Object Vspecial_display_function;
  123. #endif
  124.  
  125. /* Fdisplay_buffer always splits the largest window 
  126.    if that window is more than this high.  */
  127. int split_height_threshold;
  128.  
  129. /* Fdisplay_buffer always splits the largest window 
  130.    if that window is more than this wide.  */
  131. int split_width_threshold;
  132.  
  133. /* Number of lines of continuity in scrolling by screenfuls.  */
  134. int next_screen_context_lines;
  135.  
  136. #define SET_LAST_MODIFIED(w, cache_too)        \
  137. do {                        \
  138.   (w)->last_modified[CURRENT_DISP] = Qzero;    \
  139.   (w)->last_modified[DESIRED_DISP] = Qzero;    \
  140.   (w)->last_modified[CMOTION_DISP] = Qzero;    \
  141.   if (cache_too)                \
  142.     (w)->line_cache_last_updated = Qzero;    \
  143. } while (0)
  144.  
  145. #define SET_LAST_FACECHANGE(w)            \
  146. do {                        \
  147.   (w)->last_facechange[CURRENT_DISP] = Qzero;    \
  148.   (w)->last_facechange[DESIRED_DISP] = Qzero;    \
  149.   (w)->last_facechange[CMOTION_DISP] = Qzero;    \
  150. } while (0)
  151.  
  152.  
  153. DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
  154.   "Return t if OBJ is a window.")
  155.   (obj)
  156.      Lisp_Object obj;
  157. {
  158.   return (WINDOWP (obj) ? Qt : Qnil);
  159. }
  160.  
  161. DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
  162.   "Return t if OBJ is a window which is currently visible.")
  163.      (obj)
  164.      Lisp_Object obj;
  165. {
  166.   return (WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil);
  167. }
  168.  
  169. static Lisp_Object mark_window (Lisp_Object, void (*) (Lisp_Object));
  170. static void print_window (Lisp_Object, Lisp_Object, int);
  171. static void finalize_window (void *header, int for_disksave);
  172. DEFINE_LRECORD_IMPLEMENTATION ("window", window,
  173.                                mark_window, print_window, finalize_window,
  174.                    0, 0, struct window);
  175.  
  176. #define MARK_DISP_VARIABLE(field)            \
  177.   ((markobj) (window->field[CURRENT_DISP]));        \
  178.   ((markobj) (window->field[DESIRED_DISP]));        \
  179.   ((markobj) (window->field[CMOTION_DISP]));
  180.  
  181. static Lisp_Object
  182. mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
  183. {
  184.   struct window *window = XWINDOW (obj);
  185.   ((markobj) (window->frame));
  186.   ((markobj) (window->mini_p));
  187.   ((markobj) (window->next));
  188.   ((markobj) (window->prev));
  189.   ((markobj) (window->hchild));
  190.   ((markobj) (window->vchild));
  191.   ((markobj) (window->parent));
  192.   ((markobj) (window->buffer));
  193.   MARK_DISP_VARIABLE (start);
  194.   MARK_DISP_VARIABLE (pointm);
  195.   ((markobj) (window->sb_point));    /* #### move to scrollbar.c? */
  196.   ((markobj) (window->use_time));
  197.   MARK_DISP_VARIABLE (last_modified);
  198.   MARK_DISP_VARIABLE (last_point);
  199.   MARK_DISP_VARIABLE (last_start);
  200.   MARK_DISP_VARIABLE (last_facechange);
  201.   ((markobj) (window->line_cache_last_updated));
  202.   /* Cached specifiers: */
  203.   ((markobj) (window->display_table));
  204.   ((markobj) (window->has_modeline_p));
  205.   ((markobj) (window->modeline_shadow_thickness));
  206.   ((markobj) (window->scrollbar_width));
  207.   ((markobj) (window->scrollbar_height));
  208.   ((markobj) (window->left_margin_width));
  209.   ((markobj) (window->right_margin_width));
  210.   ((markobj) (window->toolbar_size[0]));
  211.   ((markobj) (window->toolbar_size[1]));
  212.   ((markobj) (window->toolbar_size[2]));
  213.   ((markobj) (window->toolbar_size[3]));
  214.   ((markobj) (window->minimum_line_ascent));
  215.   ((markobj) (window->minimum_line_descent));
  216.   ((markobj) (window->use_left_overflow));
  217.   ((markobj) (window->use_right_overflow));
  218.   ((markobj) (window->menubar_visible_p));
  219.   ((markobj) (window->toolbar_buttons_captioned_p));
  220.   /* End cached specifiers. */
  221.   ((markobj) (window->dedicated));
  222.   mark_face_cache_elements (window->face_cache_elements, markobj);
  223.   mark_glyph_cache_elements (window->glyph_cache_elements, markobj);
  224.   return (Qnil);
  225. }
  226.   
  227. static void
  228. print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
  229. {
  230.   char buf[200];
  231.  
  232.   if (print_readably)
  233.     error ("printing unreadable object #<window 0x%x>",
  234.            XWINDOW (obj)->header.uid);
  235.       
  236.   write_c_string ("#<window", printcharfun);
  237.   if (!NILP (XWINDOW (obj)->buffer))
  238.   {
  239.     Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
  240.     write_c_string (" on ", printcharfun);
  241.     print_internal (name, printcharfun, 1);
  242.   }
  243.   sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
  244.   write_c_string (buf, printcharfun);
  245. }
  246.  
  247. static void
  248. finalize_window (void *header, int for_disksave)
  249. {
  250.   struct window *w = (struct window *) header;
  251.  
  252.   if (w->line_start_cache)
  253.     {
  254.       Dynarr_free (w->line_start_cache);
  255.       w->line_start_cache = 0;
  256.     }
  257.  
  258.   if (w->face_cache_elements)
  259.     {
  260.       Dynarr_free (w->face_cache_elements);
  261.       w->face_cache_elements = 0;
  262.     }
  263.  
  264.   if (w->glyph_cache_elements)
  265.     {
  266.       Dynarr_free (w->glyph_cache_elements);
  267.       w->glyph_cache_elements = 0;
  268.     }
  269. }
  270.  
  271. #define INIT_DISP_VARIABLE(field, initialization)    \
  272.   p->field[CURRENT_DISP] = initialization;        \
  273.   p->field[DESIRED_DISP] = initialization;        \
  274.   p->field[CMOTION_DISP] = initialization;
  275.  
  276. /* We have an implicit assertion that the first two elements (default
  277.    and modeline faces) are always present in the face_element_cache.
  278.    Normally redisplay ensures this.  However, it is possible for a
  279.    window to get created and functions which reference these values
  280.    called before redisplay works with the window for the first time.
  281.    All callers of allocate_window should therefore call
  282.    reset_face_cache_elements on the created window.  We can't do it
  283.    here because the window must have its frame pointer set or
  284.    reset_face_cache_elements will fail. */
  285. Lisp_Object
  286. allocate_window (void)
  287. {
  288.   Lisp_Object val = Qnil;
  289.   struct window *p = alloc_lcrecord (sizeof (struct window),
  290.                      lrecord_window);
  291.  
  292.   XSETWINDOW (val, p);
  293.  
  294.   p->dead = 0;
  295.   p->frame = Qnil;
  296.   p->mini_p = Qnil;
  297.   p->next = Qnil;
  298.   p->prev = Qnil;
  299.   p->hchild = Qnil;  
  300.   p->vchild = Qnil; 
  301.   p->parent = Qnil;
  302.   p->pixel_left = 0;
  303.   p->pixel_top = 0;
  304.   p->pixel_height = 0;
  305.   p->pixel_width = 0;
  306.   p->buffer = Qnil;
  307.   INIT_DISP_VARIABLE (start, Fmake_marker ());
  308.   INIT_DISP_VARIABLE (pointm, Fmake_marker ());
  309.   p->sb_point = Fmake_marker ();
  310.   p->force_start = 0;
  311.   p->hscroll = 0;
  312.   p->use_time = Qzero;
  313.   INIT_DISP_VARIABLE (last_modified, Qzero);
  314.   INIT_DISP_VARIABLE (last_point, Fmake_marker ());
  315.   INIT_DISP_VARIABLE (last_start, Fmake_marker ());
  316.   INIT_DISP_VARIABLE (last_facechange, Qzero);
  317.   p->face_cache_elements = Dynarr_new (struct face_cache_element);
  318.   p->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
  319.   p->line_start_cache = Dynarr_new (struct line_start_cache);
  320.   p->line_cache_last_updated = Qzero;
  321.   p->line_cache_validation_override = 0;
  322.   p->max_line_len = 0;
  323.   p->config_mark = 0;
  324.   INIT_DISP_VARIABLE (last_point_x, 0);
  325.   INIT_DISP_VARIABLE (last_point_y, 0);
  326.   INIT_DISP_VARIABLE (window_end_pos, 0);
  327.   p->redo_modeline = 0;
  328.   p->start_at_line_beg = 0;
  329.   /* cached specifier values: will get set properly later */
  330.   p->display_table = Qnil;
  331.   p->has_modeline_p = Qnil;
  332.   p->modeline_shadow_thickness = Qnil;
  333.   p->scrollbar_width = Qnil;
  334.   p->scrollbar_height = Qnil;
  335.   p->left_margin_width = Qnil;
  336.   p->right_margin_width = Qnil;
  337.   p->toolbar_size[0] = Qnil;
  338.   p->toolbar_size[1] = Qnil;
  339.   p->toolbar_size[2] = Qnil;
  340.   p->toolbar_size[3] = Qnil;
  341.   p->minimum_line_ascent = Qnil;
  342.   p->minimum_line_descent = Qnil;
  343.   p->use_left_overflow = Qnil;
  344.   p->use_right_overflow = Qnil;
  345.   p->menubar_visible_p = Qnil;
  346.   p->toolbar_buttons_captioned_p = Qnil;
  347.   /* end cached specifier values. */
  348.  
  349.   p->dedicated = Qnil;
  350.   p->windows_changed = 1;
  351.   p->shadow_thickness_changed = 1;
  352.  
  353.   return (val);
  354. }
  355. #undef INIT_DISP_VARIABLE
  356.  
  357. /*
  358.  * The redisplay structures used to be stored with each window.  While
  359.  * they are logically something associated with frames they can't be
  360.  * stored there with a redisplay which handles variable height lines.
  361.  * Lines in horizontally split windows might not line up.  So they get
  362.  * stored with the windows.
  363.  *
  364.  * The problem with this is window configurations.  When restoring a
  365.  * window configuration it now becomes problematic to do an
  366.  * incremental redisplay.  The solution is to store the redisplay
  367.  * structures with the frame as they should be but laid out in the
  368.  * same manner as the window structure.  Thus is born the window
  369.  * mirror.
  370.  *
  371.  * It also becomes a convenient place to stick scrollbar instances
  372.  * since they extrapolate out to having the same problem described for
  373.  * the display structures.
  374.  */
  375.  
  376. /* Create a new mindow mirror structure and associated redisplay
  377.    structs. */
  378. static struct window_mirror *
  379. new_window_mirror (struct frame *f)
  380. {
  381.   struct window_mirror *t;
  382.  
  383.   t = (struct window_mirror *)
  384.     xmalloc (sizeof (struct window_mirror));
  385.   memset (t, 0, sizeof (struct window_mirror));
  386.  
  387.   t->frame = f;
  388.  
  389.   t->current_display_lines = Dynarr_new (struct display_line);
  390.   t->desired_display_lines = Dynarr_new (struct display_line);
  391.   t->cmotion_display_lines = Dynarr_new (struct display_line);
  392.   t->buffer = NULL;
  393.  
  394.   t->scrollbar_vertical_instance = NULL;
  395.   t->scrollbar_horizontal_instance = NULL;
  396.  
  397.   return t;
  398. }
  399.  
  400. /* Synchronize the mirror structure with a given window structure.
  401.    This is normally called from update_frame_window_mirror with a
  402.    starting window of f->root_window. */
  403. static struct window_mirror *
  404. update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
  405. {
  406.   if (NILP (win))
  407.     {
  408.       if (mir)
  409.     {
  410.       free_window_mirror (mir);
  411.       mir = 0;
  412.     }
  413.       return mir;
  414.     }
  415.   else
  416.     if (!mir)
  417.       mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
  418.  
  419.   mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
  420.   mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
  421.   mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
  422.  
  423.   /*
  424.    * If the redisplay structs are not empty and the mirror has
  425.    * children, then this mirror structure was formerly being used for
  426.    * display but is no longer.  Reset its current display structs so
  427.    * that redisplay doesn't accidentally think they are accurate if it
  428.    * is later used for display purposes once again.  Also, mark the
  429.    * scrollbar instance as not active.
  430.    */
  431.   if (mir->vchild || mir->hchild)
  432.     {
  433.       /* Reset both sets of lines.  The assertion is that outside of
  434.          redisplay, these are always identical. */
  435.       Dynarr_reset (mir->current_display_lines);
  436.       Dynarr_reset (mir->desired_display_lines);
  437.       update_window_scrollbars (XWINDOW (win), mir, 0, 0);
  438.       mir->buffer = NULL;
  439.     }
  440.  
  441.   return mir;
  442. }
  443.  
  444. /* Given a window mirror, determine which real window it contains the
  445.    redisplay structures for. */
  446. static Lisp_Object
  447. real_window_internal (Lisp_Object win, struct window_mirror *rmir,
  448.               struct window_mirror *mir)
  449. {
  450.   Lisp_Object retval;
  451.  
  452.   for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
  453.     {
  454.       if (mir == rmir)
  455.     return win;
  456.       if (!NILP (XWINDOW (win)->vchild))
  457.     {
  458.       retval = real_window_internal (XWINDOW (win)->vchild, rmir->vchild,
  459.                      mir);
  460.       if (!NILP (retval))
  461.         return retval;
  462.     }
  463.       if (!NILP (XWINDOW (win)->hchild))
  464.     {
  465.       retval = real_window_internal (XWINDOW (win)->hchild, rmir->hchild,
  466.                      mir);
  467.       if (!NILP (retval))
  468.         return retval;
  469.     }
  470.     }
  471.  
  472.   return Qnil;
  473. }
  474.  
  475. /* Given a real window, find the mirror structure which contains its
  476.    redisplay structures. */
  477. static struct window_mirror *
  478. find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
  479.                 struct window *w)
  480. {
  481.   struct window_mirror *retval;
  482.  
  483.   for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
  484.     {
  485.       if (w == XWINDOW (win))
  486.     return rmir;
  487.       if (!NILP (XWINDOW (win)->vchild) &&
  488.       (retval = find_window_mirror_internal (XWINDOW (win)->vchild,
  489.                          rmir->vchild, w)))
  490.     return retval;
  491.       if (!NILP (XWINDOW (win)->hchild) &&
  492.       (retval = find_window_mirror_internal (XWINDOW (win)->hchild,
  493.                          rmir->hchild, w)))
  494.     return retval;
  495.     }
  496.  
  497.   return 0;
  498. }
  499.  
  500. /* Update the mirror structure for the given frame. */
  501. void
  502. update_frame_window_mirror (struct frame *f)
  503. {
  504.   f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
  505.   f->mirror_dirty = 0;
  506. }
  507.  
  508. /* Free a given mirror structure along with all of its children as
  509.    well as their associated display structures. */
  510. void
  511. free_window_mirror (struct window_mirror *mir)
  512. {
  513.   struct window_mirror *p;
  514.  
  515.   p = mir;
  516.   while (mir)
  517.     {
  518.       if (mir->hchild) free_window_mirror (mir->hchild);
  519.       if (mir->vchild) free_window_mirror (mir->vchild);
  520.       release_window_mirror_scrollbars (mir);
  521.       free_display_structs (mir);
  522.       mir = mir->next;
  523.       xfree (p);
  524.       p = mir;
  525.     }
  526. }
  527.  
  528. /* Given a mirror structure, return the window it mirrors.  Calls
  529.    real_window_internal to do most of the work. */
  530. Lisp_Object
  531. real_window (struct window_mirror *mir, int no_abort)
  532. {
  533.   Lisp_Object retval;
  534.  
  535.   retval = real_window_internal (mir->frame->root_window,
  536.                  mir->frame->root_mirror, mir);
  537.  
  538.   if (NILP (retval) && !no_abort)
  539.     abort ();
  540.  
  541.   return retval;
  542. }
  543.  
  544. /* Given a real window, return its mirror structure.  Calls
  545.    find_window_mirror_internal to do all of the work. */
  546. struct window_mirror *
  547. find_window_mirror (struct window *w)
  548. {
  549.   struct frame *f = XFRAME (w->frame);
  550.   if (f->mirror_dirty)
  551.     update_frame_window_mirror (f);
  552.   return find_window_mirror_internal (f->root_window, f->root_mirror, w);
  553. }
  554.  
  555. /*****************************************************************************
  556.  find_window_by_pixel_pos
  557.  
  558.  Given a pixel position relative to a frame, find the window at that
  559.  position.
  560.  ****************************************************************************/
  561. struct window *
  562. find_window_by_pixel_pos (unsigned int pix_x, unsigned int pix_y,
  563.               Lisp_Object win)
  564. {
  565.   struct window *w;
  566.  
  567.   if (NILP (win))
  568.     return 0;
  569.  
  570.   for (; !NILP (win); win = XWINDOW (win)->next)
  571.     {
  572.       if (!NILP (XWINDOW (win)->vchild) &&
  573.       (w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild)))
  574.     return w;
  575.       if (!NILP (XWINDOW (win)->hchild) &&
  576.       (w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild)))
  577.     return w;
  578.       w = XWINDOW (win);
  579.       if (pix_x >= WINDOW_LEFT (w)
  580.       && pix_x <= WINDOW_RIGHT (w)
  581.       && pix_y >= WINDOW_TOP (w)
  582.       && pix_y <= WINDOW_BOTTOM (w))
  583.     return w;
  584.     }
  585.   return 0;
  586. }
  587.  
  588. /* Return a pointer to the display structures for the given window. */
  589. display_line_dynarr *
  590. window_display_lines (struct window *w, int which)
  591. {
  592.   struct window_mirror *t;
  593.  
  594.   if (XFRAME (w->frame)->mirror_dirty)
  595.     update_frame_window_mirror (XFRAME (w->frame));
  596.   t = find_window_mirror (w);
  597.   if (!t)
  598.     abort ();
  599.  
  600.   if (which == CURRENT_DISP)
  601.     return t->current_display_lines;
  602.   else if (which == DESIRED_DISP)
  603.     return t->desired_display_lines;
  604.   else if (which == CMOTION_DISP)
  605.     return t->cmotion_display_lines;
  606.   else
  607.     abort ();
  608.  
  609.   return 0;    /* shut up compiler */
  610. }
  611.  
  612. struct buffer *
  613. window_display_buffer (struct window *w)
  614. {
  615.   struct window_mirror *t;
  616.  
  617.   if (XFRAME (w->frame)->mirror_dirty)
  618.     update_frame_window_mirror (XFRAME (w->frame));
  619.   t = find_window_mirror (w);
  620.   if (!t)
  621.     abort ();
  622.  
  623.   return t->buffer;
  624. }
  625.  
  626. void
  627. set_window_display_buffer (struct window *w, struct buffer *b)
  628. {
  629.   struct window_mirror *t;
  630.  
  631.   if (XFRAME (w->frame)->mirror_dirty)
  632.     update_frame_window_mirror (XFRAME (w->frame));
  633.   t = find_window_mirror (w);
  634.   if (!t)
  635.     abort ();
  636.  
  637.   t->buffer = b;
  638. }
  639.  
  640.  
  641. /* Determining a windows position based solely on its pixel
  642.    positioning doesn't work.  Instead, we do it the intelligent way,
  643.    by checking its positioning in the window hierarchy. */
  644. int
  645. window_is_leftmost (struct window *w)
  646. {
  647.   Lisp_Object parent, current_ancestor, window;
  648.  
  649.   XSETWINDOW (window, w);
  650.  
  651.   parent = XWINDOW (window)->parent;
  652.   current_ancestor = window;
  653.  
  654.   while (!NILP (parent))
  655.     {
  656.       if (!NILP (XWINDOW (parent)->hchild) &&
  657.       !EQ (XWINDOW (parent)->hchild, current_ancestor))
  658.     return 0;
  659.  
  660.       current_ancestor = parent;
  661.       parent = XWINDOW (parent)->parent;
  662.     }
  663.  
  664.   return 1;
  665. }
  666.  
  667. int
  668. window_is_rightmost (struct window *w)
  669. {
  670.   Lisp_Object parent, current_ancestor, window;
  671.  
  672.   XSETWINDOW (window, w);
  673.  
  674.   parent = XWINDOW (window)->parent;
  675.   current_ancestor = window;
  676.  
  677.   while (!NILP (parent))
  678.     {
  679.       if (!NILP (XWINDOW (parent)->hchild)
  680.       && !NILP (XWINDOW (current_ancestor)->next))
  681.     return 0;
  682.  
  683.       current_ancestor = parent;
  684.       parent = XWINDOW (parent)->parent;
  685.     }
  686.  
  687.   return 1;
  688. }
  689.  
  690. int
  691. window_truncation_on (struct window *w)
  692. {
  693.   /* Horizontally scrolled windows are truncated. */
  694.   if (w->hscroll)
  695.     return 1;
  696.  
  697.   /* If truncate_partial_width_windows is true and the window is not
  698.      the full width of the frame it is truncated. */
  699.   if (truncate_partial_width_windows
  700.       && !(window_is_leftmost (w) && window_is_rightmost (w)))
  701.     return 1;
  702.  
  703.   /* If the window's buffer's value of truncate_lines is non-nil, then
  704.      the window is truncated. */
  705.   if (!NILP (XBUFFER (w->buffer)->truncate_lines))
  706.     return 1;
  707.  
  708.   return 0;
  709. }
  710.  
  711. int
  712. window_needs_vertical_divider (struct window *w)
  713. {
  714.   struct frame *f = XFRAME (w->frame);
  715.  
  716.   if (!window_scrollbar_width (w))
  717.     {
  718.       if (f->scrollbar_on_left)
  719.     return (!window_is_leftmost (w));
  720.       else
  721.     return (!window_is_rightmost (w));
  722.     }
  723.   else
  724.     return 0;
  725. }
  726.  
  727. int
  728. window_scrollbar_width (struct window *w)
  729. {
  730.   if (WINDOW_IS_TTY (w)
  731.       || MINI_WINDOW_P (w)
  732.       || NILP (w->buffer))
  733.     /* #### when does NILP (w->buffer) happen? */
  734.     return 0;
  735.  
  736.   return XINT (w->scrollbar_width);
  737. }
  738.  
  739. /* Horizontal scrollbars are only active on windows with truncation
  740.    turned on. */
  741. int
  742. window_scrollbar_height (struct window *w)
  743. {
  744.   if (WINDOW_IS_TTY (w)
  745.       || MINI_WINDOW_P (w)
  746.       || NILP (w->buffer)
  747.       || !window_truncation_on (w))
  748.     return 0;
  749.  
  750.   return XINT (w->scrollbar_height);
  751. }
  752.  
  753. /* #### When we finally get embedded faces in the modeline, this
  754.    function will need to get smarter. */
  755. int
  756. window_modeline_height (struct window *w)
  757. {
  758.   struct frame *f = XFRAME (w->frame);
  759.   struct device *d = XDEVICE (f->device);
  760.   int modeline_height;
  761.  
  762.   if (MINI_WINDOW_P (w) || NILP (w->buffer))
  763.     {
  764.       modeline_height = 0;
  765.     }
  766.   else if (!WINDOW_HAS_MODELINE_P (w))
  767.     {
  768.       if (window_scrollbar_height (w))
  769.     modeline_height = 0;
  770.       else
  771.     {
  772.       modeline_height = DEVMETH (d, divider_height, ());
  773.  
  774.       if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_IS_WIN (f))
  775.         modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
  776.     }
  777.     }
  778.   else
  779.     {
  780.       struct font_metric_info fm;
  781.  
  782.       if (noninteractive)
  783.     modeline_height = 0;
  784.       else
  785.     {
  786.       DEVMETH (d, font_metric_info,
  787.            (d, FACE_CACHE_ELEMENT_FONT (w, MODELINE_INDEX), &fm));
  788.       modeline_height = fm.ascent + fm.descent;
  789.  
  790.       if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_IS_WIN (f))
  791.         modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
  792.     }
  793.     }
  794.  
  795.   return modeline_height;
  796. }
  797.  
  798. /*****************************************************************************
  799.  margin_width_internal
  800.  
  801.  For a given window, return the width in pixels of the specified margin.
  802.  ****************************************************************************/
  803. static int
  804. margin_width_internal (struct window *w, int left_margin)
  805. {
  806.   struct buffer *b;
  807.   struct frame *f = XFRAME (w->frame);
  808.   struct device *d = XDEVICE (f->device);
  809.   struct font_metric_info fm;
  810.   int window_cwidth = window_char_width (w, 1);
  811.   int margin_cwidth;
  812.  
  813.   /* We might be getting called on a non-leaf. */
  814.   if (NILP (w->buffer))
  815.     return 0;
  816.  
  817.   /* The minibuffer never has margins. */
  818.   if (MINI_WINDOW_P (w))
  819.     return 0;
  820.  
  821.   b = XBUFFER (w->buffer);
  822.   margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
  823.            XINT (w->right_margin_width));
  824.  
  825.   /* We need the default character width. */
  826.   DEVMETH (d, font_metric_info, (d, FACE_CACHE_ELEMENT_FONT (w, DEFAULT_INDEX),
  827.                  &fm));
  828.  
  829.   /* The left margin takes precedence over the right margin so we
  830.      subtract its width from the space available for the right
  831.      margin. */
  832.   if (!left_margin)
  833.     window_cwidth -= XINT (w->left_margin_width);
  834.  
  835.   /* The margin cannot be wider than the window is.  We allow the
  836.      value to be bigger since it is possible for the user to enlarge
  837.      the window such that the left margin value would no longer be too
  838.      big, but we won't return a value that is larger. */
  839.   if (margin_cwidth > window_cwidth)
  840.     margin_cwidth = window_cwidth;
  841.  
  842.   /* At the user level the margin is always specified in characters.
  843.      Internally however it is manipulated in terms of pixels. */
  844.   return (margin_cwidth * fm.width);
  845. }
  846.  
  847. int
  848. window_left_margin_width (struct window *w)
  849. {
  850.   return margin_width_internal (w, 1);
  851. }
  852.  
  853. int
  854. window_right_margin_width (struct window *w)
  855. {
  856.   return margin_width_internal (w, 0);
  857. }
  858.  
  859. static int
  860. window_top_toolbar_height (struct window *w)
  861. {
  862.   /* #### implement this shit. */
  863.   return 0;
  864. }
  865.  
  866. /* #### Currently used in scrollbar.c.  Does it actually need to be? */
  867. int
  868. window_bottom_toolbar_height (struct window *w)
  869. {
  870.   return 0;
  871. }
  872.  
  873. static int
  874. window_left_toolbar_width (struct window *w)
  875. {
  876.   return 0;
  877. }
  878.  
  879. static int
  880. window_right_toolbar_width (struct window *w)
  881. {
  882.   return 0;
  883. }
  884.  
  885. /*****************************************************************************
  886.  Window Gutters
  887.  
  888.  The gutters of a window are those areas in the boundary defined by
  889.  w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
  890.  do not contain text.  Items which may be in the gutters include
  891.  scrollbars, toolbars and modelines.  The margin areas are not
  892.  included.  This is an exception made because redisplay special cases
  893.  the handling of those areas in many places in such a way that
  894.  including them in the gutter area would make life difficult.
  895.  
  896.  The size functions refer to height for the bottom and top gutters and
  897.  width for the left and right gutters.  The starting position
  898.  functions refer to the Y coord for bottom and top gutters and the X
  899.  coord for left and right gutters.  All starting positions are
  900.  relative to the frame, not the window.
  901.  ****************************************************************************/
  902.  
  903. int
  904. window_top_gutter_height (struct window *w)
  905. {
  906.   struct frame *f = XFRAME (w->frame);
  907.   int toolbar_height = window_top_toolbar_height (w);
  908.  
  909.   if (!NILP (w->hchild) || !NILP (w->vchild))
  910.     return 0;
  911.  
  912.   if (f->scrollbar_on_top)
  913.     return window_scrollbar_height (w) + toolbar_height;
  914.   else
  915.     return toolbar_height;
  916. }
  917.  
  918. int
  919. window_bottom_gutter_height (struct window *w)
  920. {
  921.   struct frame *f = XFRAME (w->frame);
  922.   int other_height;    
  923.  
  924.   if (!NILP (w->hchild) || !NILP (w->vchild))
  925.     return 0;
  926.   else
  927.     other_height =
  928.       window_modeline_height (w) + window_bottom_toolbar_height (w);
  929.  
  930.   if (!f->scrollbar_on_top)
  931.     return window_scrollbar_height (w) + other_height;
  932.   else
  933.     return other_height;
  934. }
  935.  
  936. static int
  937. window_left_right_gutter_width_internal (struct window *w, int modeline)
  938. {
  939.   struct device *d = XDEVICE (XFRAME (w->frame)->device);
  940.   int scrollbar_width = window_scrollbar_width (w);
  941.  
  942.   if (!NILP (w->hchild) || !NILP (w->vchild))
  943.     return 0;
  944.  
  945.   if (!modeline)
  946.     {
  947.       if (scrollbar_width)
  948.     return scrollbar_width;
  949.       else if (window_needs_vertical_divider (w))
  950.     return DEVMETH (d, divider_width, ());
  951.       else
  952.     return 0;
  953.     }
  954.   else
  955.     {
  956.       /* The shadows on the 3D modelines provide a visual break
  957.          between the modelines of horizontally split windows.  2D
  958.          modelines need some help, though. */
  959.       if (!EQ (Qzero, w->modeline_shadow_thickness))
  960.     return 0;
  961.       else if (window_needs_vertical_divider (w))
  962.     return DEVMETH (d, divider_width, ());
  963.       else
  964.     return 0;
  965.     }
  966. }
  967.  
  968. int
  969. window_left_gutter_width (struct window *w, int modeline)
  970. {
  971.   struct frame *f = XFRAME (w->frame);
  972.  
  973.   if (!NILP (w->hchild) || !NILP (w->vchild))
  974.     return 0;
  975.  
  976.   if (f->scrollbar_on_left)
  977.     {
  978.       return (window_left_right_gutter_width_internal (w, modeline) +
  979.           window_left_toolbar_width (w));
  980.     }
  981.   else
  982.     return window_left_toolbar_width (w);
  983. }
  984.  
  985. int
  986. window_right_gutter_width (struct window *w, int modeline)
  987. {
  988.   struct frame *f = XFRAME (w->frame);
  989.  
  990.   if (!NILP (w->hchild) || !NILP (w->vchild))
  991.     return 0;
  992.  
  993.   if (!f->scrollbar_on_left)
  994.     {
  995.       return (window_left_right_gutter_width_internal (w, modeline) +
  996.           window_right_toolbar_width (w));
  997.     }
  998.   else
  999.     return window_right_toolbar_width (w);
  1000. }
  1001.  
  1002.  
  1003. DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 1, 0,
  1004.   "Return the window that the cursor now appears in and commands apply to.\n\
  1005. If DEVICE is not specified, the selected device is used.")
  1006.      (device)
  1007.      Lisp_Object device;
  1008. {
  1009.   Lisp_Object frame;
  1010.  
  1011.   if (NILP (device) && NILP (Fselected_device ()))
  1012.     return Qnil; /* happens at startup */
  1013.  
  1014.   XSETDEVICE (device, get_device (device));
  1015.   frame = Fselected_frame (device);
  1016.   if (NILP (frame))
  1017.     return Qnil;
  1018.   else
  1019.     return FRAME_SELECTED_WINDOW (XFRAME (frame));
  1020. }
  1021.  
  1022. DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
  1023.   "Return the window used now for minibuffers.\n\
  1024. If the optional argument DEV-OR-FRAME is specified and is a frame, return\n\
  1025. the minibuffer window used by that frame.  If DEV-OR-FRAME is a device,\n\
  1026. then the selected frame on that device will be used.  Otherwise, the\n\
  1027. selected frame on the current device is assumed.")
  1028.      (dev_or_frame)
  1029.      Lisp_Object dev_or_frame;
  1030. {
  1031.   Lisp_Object result;
  1032.   struct frame *f;
  1033.  
  1034.   if (DEVICEP (dev_or_frame))
  1035.     f = device_selected_frame (XDEVICE (dev_or_frame));
  1036.   else
  1037.     f = get_frame (dev_or_frame);
  1038.  
  1039.   result = FRAME_MINIBUF_WINDOW (f);
  1040.   if (WINDOWP (result))
  1041.     return (result);
  1042.  
  1043.   choose_minibuf_frame ();     /*#### Is this crock needed here??? */
  1044.  
  1045.   return (minibuf_window);
  1046. }
  1047.  
  1048. DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 1, 1, 0,
  1049.   "Return non-nil if WINDOW is a minibuffer window.")
  1050.   (window)
  1051.      Lisp_Object window;
  1052. {
  1053.   struct window *w = decode_window (window);
  1054.   return (MINI_WINDOW_P (w) ? Qt : Qnil);
  1055. }
  1056.  
  1057. DEFUN ("window-lowest-p", Fwindow_lowest_p, Swindow_lowest_p, 1, 1, 0,
  1058.   "Return non-nil if WINDOW is along the bottom of its frame.")
  1059.      (window)
  1060.      Lisp_Object window;
  1061. {
  1062.   struct window *w = decode_window (window);
  1063.   int offset;
  1064.   Lisp_Object cur_window;
  1065.  
  1066.   XSETWINDOW (window, w);
  1067.  
  1068.   /* Fframe_lowest_window returns nil once the offset is greater than
  1069.      the number of windows along the bottom. */
  1070.   offset = 0;
  1071.   do
  1072.     {
  1073.       cur_window = Fframe_lowest_window (w->frame, make_number (offset));
  1074.  
  1075.       if (EQ (cur_window, window))
  1076.     return Qt;
  1077.       offset++;
  1078.     }
  1079.   while (!NILP (cur_window));
  1080.  
  1081.   return Qnil;
  1082. }
  1083.  
  1084. DEFUN ("window-highest-p", Fwindow_highest_p, Swindow_highest_p, 1, 1, 0,
  1085.   "Return non-nil if WINDOW is along the top of its frame.")
  1086.      (window)
  1087.      Lisp_Object window;
  1088. {
  1089.   struct window *w = decode_window (window);
  1090.   int offset;
  1091.   Lisp_Object cur_window;
  1092.  
  1093.   XSETWINDOW (window, w);
  1094.  
  1095.   /* Fframe_highest_window returns nil once the offset is greater than
  1096.      the number of windows along the top. */
  1097.   offset = 0;
  1098.   do
  1099.     {
  1100.       cur_window = Fframe_highest_window (w->frame, make_number (offset));
  1101.  
  1102.       if (EQ (cur_window, window))
  1103.     return Qt;
  1104.       offset++;
  1105.     }
  1106.   while (!NILP (cur_window));
  1107.  
  1108.   return Qnil;
  1109. }
  1110.  
  1111. DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
  1112.   Spos_visible_in_window_p, 0, 2, 0,
  1113.   "Return t if position POS is currently on the frame in WINDOW.\n\
  1114. Returns nil if that position is scrolled vertically out of view.\n\
  1115. POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.")
  1116.   (pos, window)
  1117.      Lisp_Object pos, window;
  1118. {
  1119.   struct window *w;
  1120.   Bufpos top;
  1121.   Bufpos posint;
  1122.   struct buffer *buf;
  1123.  
  1124.   w = decode_window (window);
  1125.   top = marker_position (w->start[CURRENT_DISP]);
  1126.  
  1127.   buf = XBUFFER (w->buffer);
  1128.  
  1129.   if (NILP (pos))
  1130.     posint = BUF_PT (buf);
  1131.   else
  1132.     {
  1133.       CHECK_INT_COERCE_MARKER (pos, 0);
  1134.       posint = XINT (pos);
  1135.     }
  1136.  
  1137.   if (posint < top || posint > BUF_ZV (buf))
  1138.     return Qnil;
  1139.  
  1140.   /* w->start can be out of range.  If it is, do something reasonable.  */
  1141.   if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
  1142.     return Qnil;
  1143.  
  1144.   if (point_would_be_visible (w, top, posint))
  1145.     return Qt;
  1146.   else
  1147.     return Qnil;
  1148. }
  1149.  
  1150.  
  1151. struct window *
  1152. decode_window (Lisp_Object window)
  1153. {
  1154.   if (NILP (window))
  1155.     return XWINDOW (Fselected_window (Qnil));
  1156.  
  1157.   CHECK_LIVE_WINDOW (window, 0);
  1158.   return XWINDOW (window);
  1159. }
  1160.  
  1161. DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
  1162.   "Return the buffer that WINDOW is displaying.")
  1163.   (window)
  1164.      Lisp_Object window;
  1165. {
  1166.   return decode_window (window)->buffer;
  1167. }
  1168.  
  1169. DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
  1170.        "Return the frame that window WINDOW is on.")
  1171.      (window)
  1172.      Lisp_Object window;
  1173. {
  1174.   return decode_window (window)->frame;
  1175. }
  1176.  
  1177. DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
  1178.        "Return the number of lines in WINDOW (including its modeline).")
  1179.      (window)
  1180.      Lisp_Object window;
  1181. {
  1182.   return make_number (window_char_height (decode_window (window), 1));
  1183. }
  1184.  
  1185. DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height,
  1186.        0, 1, 0,
  1187.        "Return the height of WINDOW in pixels.  Defaults to current window.")
  1188.      (window)
  1189.      Lisp_Object window;
  1190. {
  1191.   return (make_number (decode_window (window)->pixel_height));
  1192. }
  1193.  
  1194. DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
  1195.        "Return the number of display columns in WINDOW.\n\
  1196. This is the width that is usable columns available for text in WINDOW.")
  1197.      (window)
  1198.      Lisp_Object window;
  1199. {
  1200.   struct window *w = decode_window (window);
  1201.   return (make_number (window_char_width (w, 0)));
  1202. }
  1203.  
  1204. DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width,
  1205.        0, 1, 0,
  1206.        "Return the width of WINDOW in pixels.  Defaults to current window.")
  1207.      (window)
  1208.      Lisp_Object window;
  1209. {
  1210.   return (make_number (decode_window (window)->pixel_width));
  1211. }
  1212.  
  1213. DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
  1214.   "Return the number of columns by which WINDOW is scrolled from left margin.")
  1215.      (window)
  1216.      Lisp_Object window;
  1217. {
  1218.   return (make_number (decode_window (window)->hscroll));
  1219. }
  1220.  
  1221. DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
  1222.   "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
  1223. NCOL should be zero or positive.")
  1224.   (window, ncol)
  1225.      Lisp_Object window, ncol;
  1226. {
  1227.   struct window *w;
  1228.   int ncols;
  1229.  
  1230.   CHECK_INT (ncol, 1);
  1231.   ncols = XINT (ncol);
  1232.   if (ncols < 0) ncols = 0;
  1233.   if (ncols >= (1 << (SHORTBITS - 1)))
  1234.     args_out_of_range (ncol, Qnil);
  1235.   w = decode_window (window);
  1236.   if (w->hscroll != ncols)
  1237.     MARK_CLIP_CHANGED;
  1238.   w->hscroll = ncols;
  1239.   return ncol;
  1240. }
  1241.  
  1242. DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges,
  1243.        0, 1, 0,
  1244.        "Return a list of the pixel edge coordinates of WINDOW.\n\
  1245. \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
  1246. The frame toolbars and menubars are considered to be outside of this area.")
  1247.      (window)
  1248.      Lisp_Object window;
  1249. {
  1250.   struct window *w = decode_window (window);
  1251.   struct frame *f = XFRAME (w->frame);
  1252.   int left, top;
  1253.  
  1254.   left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
  1255.   top = w->pixel_top - FRAME_TOP_BORDER_END (f);
  1256.  
  1257.   return list4 (make_number (left),
  1258.         make_number (top),
  1259.         make_number (left + w->pixel_width),
  1260.         make_number (top + w->pixel_height));
  1261. }
  1262.  
  1263. DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
  1264.   "Return current value of point in WINDOW.\n\
  1265. For a nonselected window, this is the value point would have\n\
  1266. if that window were selected.\n\
  1267. \n\
  1268. Note that, when WINDOW is the selected window and its buffer\n\
  1269. is also currently selected, the value returned is the same as (point).\n\
  1270. It would be more strictly correct to return the `top-level' value\n\
  1271. of point, outside of any save-excursion forms.\n\
  1272. But that is hard to define.")
  1273.   (window)
  1274.      Lisp_Object window;
  1275. {
  1276.   struct window *w = decode_window (window);
  1277.  
  1278.   /* The special check for current buffer is necessary for this
  1279.      function to work as defined when called within an excursion. */
  1280.   if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
  1281.       && current_buffer == XBUFFER (w->buffer))
  1282.     return Fpoint (Qnil);
  1283.   return Fmarker_position (w->pointm[CURRENT_DISP]);
  1284. }
  1285.  
  1286. DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
  1287.   "Return position at which display currently starts in WINDOW.")
  1288.   (window)
  1289.      Lisp_Object window;
  1290. {
  1291.   return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
  1292. }
  1293.  
  1294. DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
  1295.   "Return position at which display currently ends in WINDOW.\n\
  1296. This is updated by redisplay, when it runs to completion.\n\
  1297. Simply changing the buffer text or setting `window-start'\n\
  1298. does not update this value.\n\
  1299. If GUARANTEE is non-nil, then the return value is guaranteed to be\n\
  1300. the value of window-end at the end of the next full redisplay assuming\n\
  1301. nothing else changes in the meantime.  This function is potentially much\n\
  1302. slower with this flag set.")
  1303.   (window, guarantee)
  1304.      Lisp_Object window, guarantee;
  1305. {
  1306.   Lisp_Object value;
  1307.   struct window *w = decode_window (window);
  1308.   Lisp_Object buf;
  1309.  
  1310.   if (NILP (guarantee))
  1311.     {
  1312.       buf = w->buffer;
  1313.       CHECK_BUFFER (buf, 0);
  1314.  
  1315.       XSETINT (value, BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
  1316.  
  1317.       return value;
  1318.     }
  1319.   else
  1320.     {
  1321.       Bufpos startp = marker_position (w->start[CURRENT_DISP]);
  1322.       return (make_number (end_of_last_line (w, startp)));
  1323.     }
  1324. }
  1325.  
  1326. DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
  1327.   "Make point value in WINDOW be at position POS in WINDOW's buffer.")
  1328.   (window, pos)
  1329.      Lisp_Object window, pos;
  1330. {
  1331.   struct window *w = decode_window (window);
  1332.  
  1333.   CHECK_INT_COERCE_MARKER (pos, 1);
  1334.   if (w == XWINDOW (Fselected_window (Qnil)))
  1335.     Fgoto_char (pos, Fcurrent_buffer ());
  1336.   else
  1337.     set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
  1338.  
  1339.   MARK_POINT_CHANGED;
  1340.   return pos;
  1341. }
  1342.  
  1343. DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
  1344.   "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
  1345. Optional third arg NOFORCE non-nil inhibits next redisplay\n\
  1346. from overriding motion of point in order to display at this exact start.")
  1347.   (window, pos, noforce)
  1348.      Lisp_Object window, pos, noforce;
  1349. {
  1350.   struct window *w = decode_window (window);
  1351.  
  1352.   CHECK_INT_COERCE_MARKER (pos, 1);
  1353.   set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
  1354.   /* this is not right, but much easier than doing what is right. */
  1355.   w->start_at_line_beg = 0;
  1356.   if (NILP (noforce))
  1357.     w->force_start = 1;
  1358.   w->redo_modeline = 1;
  1359.   SET_LAST_MODIFIED (w, 0);
  1360.   SET_LAST_FACECHANGE (w);
  1361.  
  1362.   MARK_WINDOWS_CHANGED(w);
  1363.  
  1364.   return pos;
  1365. }
  1366.  
  1367. DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
  1368.        1, 1, 0,
  1369.   "Return WINDOW's dedicated object, usually t or nil.\n\
  1370. See also `set-window-buffer-dedicated'.")
  1371.   (window)
  1372.      Lisp_Object window;
  1373. {
  1374.   return decode_window (window)->dedicated;
  1375. }
  1376.  
  1377. DEFUN ("set-window-buffer-dedicated", Fset_window_buffer_dedicated,
  1378.        Sset_window_buffer_dedicated, 2, 2, 0,
  1379.   "Make WINDOW display BUFFER and be dedicated to that buffer.\n\
  1380. Then Emacs will not automatically change which buffer appears in WINDOW.\n\
  1381. If BUFFER is nil, make WINDOW not be dedicated (but don't change which\n\
  1382. buffer appears in it currently).")
  1383.   (window, buffer)
  1384.        Lisp_Object window, buffer;
  1385. {
  1386.   /* This function can GC */
  1387.   struct window *w = decode_window (window);
  1388.  
  1389.   if (NILP (buffer))
  1390.     w->dedicated = Qnil;
  1391.   else
  1392.     {
  1393.       /* Allow non-buffer argument for FSF compatibility. */
  1394.       if (BUFFERP (buffer))
  1395.     Fset_window_buffer (window, Fget_buffer_create (buffer));
  1396.       w->dedicated = Qt;
  1397.     }
  1398.  
  1399.   return w->dedicated;
  1400. }
  1401.  
  1402.  
  1403. /* Record info on buffer window w is displaying
  1404.    when it is about to cease to display that buffer.  */
  1405. static void
  1406. unshow_buffer (struct window *w)
  1407. {
  1408.   Lisp_Object buf = w->buffer;
  1409.  
  1410.   if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
  1411.     abort ();
  1412.  
  1413. #ifdef ENERGIZE
  1414.     energize_buffer_hidden_hook (w);
  1415. #endif
  1416.  
  1417.   /* FSF disables this check, so I'll do it too.  I hope it won't
  1418.      break things.  --ben */
  1419. #if 0
  1420.   if (w == XWINDOW (Fselected_window (Qnil))
  1421.       || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
  1422.     /* Do this except when the selected window's buffer
  1423.        is being removed from some other window.  */
  1424. #endif
  1425.     /* last_window_start records the start position that this buffer
  1426.        had in the last window to be disconnected from it.
  1427.        Now that this statement is unconditional,
  1428.        it is possible for the buffer to be displayed in the
  1429.        selected window, while last_window_start reflects another
  1430.        window which was recently showing the same buffer.
  1431.        Some people might say that might be a good thing.  Let's see.  */
  1432.     XBUFFER (buf)->last_window_start =
  1433.       marker_position (w->start[CURRENT_DISP]);
  1434.  
  1435.   /* Point in the selected window's buffer
  1436.      is actually stored in that buffer, and the window's pointm isn't used.
  1437.      So don't clobber point in that buffer.  */
  1438.   if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
  1439.     {
  1440.       struct buffer *b= XBUFFER (buf);
  1441.       BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
  1442.                                      marker_position (w->pointm[CURRENT_DISP]),
  1443.                                      BUF_ZV (b)));
  1444.     }
  1445. }
  1446.  
  1447. /* Put REPLACEMENT into the window structure in place of OLD. */
  1448. static void
  1449. replace_window (Lisp_Object old, Lisp_Object replacement)
  1450. {
  1451.   Lisp_Object tem;
  1452.   struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
  1453.  
  1454.   /* If OLD is its frame's root_window, then replacement is the new
  1455.      root_window for that frame.  */
  1456.  
  1457.   if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
  1458.     FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
  1459.  
  1460.   WINDOW_LEFT (p) = WINDOW_LEFT (o);
  1461.   WINDOW_TOP (p) = WINDOW_TOP (o);
  1462.   WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
  1463.   WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
  1464.  
  1465.   p->next = tem = o->next;
  1466.   if (!NILP (tem))
  1467.     XWINDOW (tem)->prev = replacement;
  1468.  
  1469.   p->prev = tem = o->prev;
  1470.   if (!NILP (tem))
  1471.     XWINDOW (tem)->next = replacement;
  1472.  
  1473.   p->parent = tem = o->parent;
  1474.   if (!NILP (tem))
  1475.     {
  1476.       if (EQ (XWINDOW (tem)->vchild, old))
  1477.     XWINDOW (tem)->vchild = replacement;
  1478.       if (EQ (XWINDOW (tem)->hchild, old))
  1479.     XWINDOW (tem)->hchild = replacement;
  1480.     }
  1481.  
  1482.   /* #### Here, if replacement is a vertical combination
  1483.      and so is its new parent, we should make replacement's
  1484.      children be children of that parent instead. */
  1485. }
  1486.  
  1487. /* we're deleting W; set the structure of W to indicate this. */
  1488.  
  1489. static void
  1490. mark_window_as_deleted (struct window *w)
  1491. {
  1492.   /* In the loop
  1493.      (while t (split-window) (delete-window))
  1494.      we end up with a tree of deleted windows which are all connected
  1495.      through the `next' slot.  This might not seem so bad, as they're
  1496.      deleted, and will presumably be GCed - but if even *one* of those
  1497.      windows is still being pointed to, by the user, or by a window
  1498.      configuration, then *all* of those windows stick around.
  1499.  
  1500.      Since the window-configuration code doesn't need any of the
  1501.      pointers to other windows (they are all recreated from the
  1502.      window-config data), we set them all to nil so that we
  1503.      are able to collect more actual garbage.
  1504.    */
  1505.   w->next = Qnil;
  1506.   w->prev = Qnil;
  1507.   w->hchild = Qnil;
  1508.   w->vchild = Qnil;
  1509.   w->parent = Qnil;
  1510.  
  1511.   w->dead = 1;
  1512.  
  1513.   /* Free the extra data structures attached to windows immediately so
  1514.      they don't sit around consuming excess space.  They will be
  1515.      reinitialized by the window-configuration code as necessary. */
  1516.   finalize_window ((void *) w, 0);
  1517. }
  1518.  
  1519. DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
  1520.   "Remove WINDOW from the display.  Default is selected window.\n\
  1521. If window is the only one on the frame, the frame is destroyed.")
  1522.   (window)
  1523.      Lisp_Object window;
  1524. {
  1525.   /* This function can GC if this is the only window in the frame */
  1526.   struct window *w;
  1527.   Lisp_Object parent;
  1528.   struct window *par;
  1529.   Lisp_Object frame;
  1530.   struct frame *f;
  1531.   struct device *d;
  1532.  
  1533.   /* Note: this function is called by other C code on non-leaf
  1534.      windows. */
  1535.  
  1536.   /* Do the equivalent of decode_window() but don't error out on
  1537.      deleted window; it's OK to delete an already-deleted window. */
  1538.   if (NILP (window))
  1539.     window = Fselected_window (Qnil);
  1540.   else
  1541.     CHECK_WINDOW (window, 0);
  1542.   w = XWINDOW (window);
  1543.  
  1544.   /* It's okay to delete an already-deleted window.  */
  1545.   if (! WINDOW_LIVE_P (w))
  1546.     return Qnil;
  1547.  
  1548.   frame = WINDOW_FRAME (w);
  1549.   f = XFRAME (frame);
  1550.   d = XDEVICE (FRAME_DEVICE (f));
  1551.  
  1552.   if (TOP_LEVEL_WINDOW_P (w))
  1553.     {
  1554.       if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
  1555.     /* this frame isn't fully initialized yet; don't blow up. */
  1556.     return Qnil;
  1557.  
  1558.       if (MINI_WINDOW_P (XWINDOW (window)))
  1559.     error ("Attempt to delete the minibuffer window");
  1560.  
  1561.       /* It has been suggested that it's a good thing for C-x 0 to have this
  1562.      behavior, but not such a good idea for #'delete-window to have it.
  1563.      Maybe C-x 0 should be bound to something else, or maybe frame
  1564.      deletion should only happen when this is called interactively.
  1565.        */
  1566.       if (EQ (frame, next_frame (frame, Qt)))
  1567.     error ("Attempt to delete the only window on the only frame");
  1568.  
  1569.       MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
  1570.       delete_frame_internal (frame, 0);
  1571.       return Qnil;
  1572.     }
  1573.  
  1574.   /* At this point, we know the window has a parent. */
  1575.   parent = w->parent;
  1576.   par = XWINDOW (parent);
  1577.  
  1578.   MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
  1579.  
  1580.   /* Are we trying to delete any frame's selected window?
  1581.      Note that we could be dealing with a non-leaf window
  1582.      where the selected window is one of our children.
  1583.      So, we check by scanning all the ancestors of the
  1584.      frame's selected window and comparing each one with
  1585.      WINDOW.  */
  1586.   {
  1587.     Lisp_Object pwindow;
  1588.     
  1589.     pwindow = FRAME_SELECTED_WINDOW (f);
  1590.     
  1591.     while (!NILP (pwindow))
  1592.       {
  1593.     if (EQ (window, pwindow))
  1594.       break;
  1595.     pwindow = XWINDOW (pwindow)->parent;
  1596.       }
  1597.  
  1598.     if (EQ (window, pwindow))
  1599.       {
  1600.     /* OK, we found it. */
  1601.     Lisp_Object alternative;
  1602.     alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
  1603.     
  1604.     /* If we're about to delete the selected window on the
  1605.        selected frame, then we should use Fselect_window to select
  1606.        the new window.  On the other hand, if we're about to
  1607.        delete the selected window on any other frame, we shouldn't do
  1608.        anything but set the frame's selected_window slot.  */
  1609.     if (EQ (frame, Fselected_frame (Qnil)))
  1610.       Fselect_window (alternative);
  1611.     else
  1612.       FRAME_SELECTED_WINDOW (f) = alternative;
  1613.       }
  1614.   }
  1615.  
  1616.   /* w->buffer is nil in a non-leaf window; in this case,
  1617.      get rid of the markers we maintain that point into that buffer. */
  1618.   if (!NILP (w->buffer))
  1619.     {
  1620.       unshow_buffer (w);
  1621.       unchain_marker (w->pointm[CURRENT_DISP]);
  1622.       unchain_marker (w->pointm[DESIRED_DISP]);
  1623.       unchain_marker (w->pointm[CMOTION_DISP]);
  1624.       unchain_marker (w->start[CURRENT_DISP]);
  1625.       unchain_marker (w->start[DESIRED_DISP]);
  1626.       unchain_marker (w->start[CMOTION_DISP]);
  1627.       unchain_marker (w->sb_point);
  1628.       /* This breaks set-window-configuration if windows in the saved
  1629.      configuration get deleted and multiple frames are in use. */
  1630.       /* w->buffer = Qnil; */
  1631.     }
  1632.     
  1633.   /* close up the hole in the sibling list */
  1634.   if (!NILP (w->next))
  1635.     XWINDOW (w->next)->prev = w->prev;
  1636.   if (!NILP (w->prev))
  1637.     XWINDOW (w->prev)->next = w->next;
  1638.   if (EQ (window, par->hchild))
  1639.     par->hchild = w->next;
  1640.   if (EQ (window, par->vchild))
  1641.     par->vchild = w->next;
  1642.  
  1643.   /* Find one of our siblings to give our space to.  */
  1644.   {
  1645.     Lisp_Object sib = w->prev;
  1646.     if (NILP (sib))
  1647.       {
  1648.     /* If w gives its space to its next sibling, that sibling needs
  1649.        to have its top/left side pulled back to where w's is.
  1650.        set_window_{height,width} will re-position the sibling's
  1651.        children.  */
  1652.     sib = w->next;
  1653.     WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
  1654.     WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
  1655.       }
  1656.     
  1657.     /* Stretch that sibling.  */
  1658.     if (!NILP (par->vchild))
  1659.       set_window_pixheight
  1660.     (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
  1661.     if (!NILP (par->hchild))
  1662.       set_window_pixwidth
  1663.     (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
  1664.   }
  1665.  
  1666.   /* If parent now has only one child,
  1667.      put the child into the parent's place.  */
  1668.   {
  1669.     Lisp_Object parchild = par->hchild;
  1670.     if (NILP (parchild))
  1671.       parchild = par->vchild;
  1672.     if (NILP (XWINDOW (parchild)->next))
  1673.       {
  1674.     replace_window (parent, parchild);
  1675.     mark_window_as_deleted (XWINDOW (parent));
  1676.       }
  1677.     }
  1678.  
  1679.   /* Since we may be deleting combination windows, we must make sure that
  1680.      not only W but all its children have been marked as deleted.  */
  1681.   if (!NILP (w->hchild))
  1682.     delete_all_subwindows (XWINDOW (w->hchild));
  1683.   else if (!NILP (w->vchild))
  1684.     delete_all_subwindows (XWINDOW (w->vchild));
  1685.  
  1686.   mark_window_as_deleted (w);
  1687.  
  1688.   f->mirror_dirty = 1;
  1689.   return Qnil;
  1690. }
  1691.  
  1692.  
  1693. DEFUN ("next-window", Fnext_window, Snext_window, 0, 4, 0,
  1694.   "Return next window after WINDOW in canonical ordering of windows.\n\
  1695. If omitted, WINDOW defaults to the selected window.\n\
  1696. \n\
  1697. Optional second arg MINIBUF t means count the minibuffer window even\n\
  1698. if not active.  MINIBUF nil or omitted means count the minibuffer iff\n\
  1699. it is active.  MINIBUF neither t nor nil means not to count the\n\
  1700. minibuffer even if it is active.\n\
  1701. \n\
  1702. Several frames may share a single minibuffer; if the minibuffer\n\
  1703. counts, all windows on all frames that share that minibuffer count\n\
  1704. too.  Therefore, `next-window' can be used to iterate through the\n\
  1705. set of windows even when the minibuffer is on another frame.  If the\n\
  1706. minibuffer does not count, only windows from WINDOW's frame count.\n\
  1707. \n\
  1708. Optional third arg ALL-FRAMES t means include windows on all frames.\n\
  1709. ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
  1710. above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
  1711. ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
  1712. Anything else means restrict to WINDOW's frame.\n\
  1713. \n\
  1714. If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
  1715. `next-window' to iterate through the entire cycle of acceptable\n\
  1716. windows, eventually ending up back at the window you started with.\n\
  1717. `previous-window' traverses the same cycle, in the reverse order.")
  1718.      (window, minibuf, all_frames, ignored)
  1719.      Lisp_Object window, minibuf, all_frames, ignored;
  1720. {
  1721.   Lisp_Object tem;
  1722.   Lisp_Object start_window;
  1723.  
  1724.   if (NILP (window))
  1725.     window = Fselected_window (Qnil);
  1726.   else
  1727.     CHECK_LIVE_WINDOW (window, 0);
  1728.  
  1729.   start_window = window;
  1730.  
  1731.   /* minibuf == nil may or may not include minibuffers.
  1732.      Decide if it does.  */
  1733.   if (NILP (minibuf))
  1734.     minibuf = (minibuf_level ? Qt : Qlambda);
  1735.  
  1736. #if 0 /* #### old code, not in FSF.  Probably should be deleted. */
  1737.   if (EQ (mini, Qt)
  1738.       || (! NILP (mini) && minibuf_level))
  1739.     {
  1740.       if (FRAMEP (Vdefault_minibuffer_frame))
  1741.     all_frames = Qt;
  1742.     }
  1743. #endif
  1744.  
  1745.   /* all_frames == nil doesn't specify which frames to include.  */
  1746.   if (NILP (all_frames))
  1747.     all_frames = (EQ (minibuf, Qt)
  1748.           ? (FRAME_MINIBUF_WINDOW
  1749.              (XFRAME
  1750.               (WINDOW_FRAME
  1751.                (XWINDOW (window)))))
  1752.           : Qnil);
  1753.   else if (EQ (all_frames, Qvisible))
  1754.     ;
  1755.   else if (EQ (all_frames, Qzero))
  1756.     ;
  1757.   else if (! EQ (all_frames, Qt))
  1758.     all_frames = Qnil;
  1759.   /* Now all_frames is t meaning search all frames,
  1760.      nil meaning search just current frame,
  1761.      visible meaning search just visible frames,
  1762.      0 meaning search visible and iconified frames,
  1763.      or a window, meaning search the frame that window belongs to.  */
  1764.  
  1765.   /* Do this loop at least once, to get the next window, and perhaps
  1766.      again, if we hit the minibuffer and that is not acceptable.  */
  1767.   do
  1768.     {
  1769.       /* Find a window that actually has a next one.  This loop
  1770.      climbs up the tree.  */
  1771.       while (tem = XWINDOW (window)->next, NILP (tem))
  1772.     if (tem = XWINDOW (window)->parent, !NILP (tem))
  1773.       window = tem;
  1774.         else  /* window must be minibuffer window now */
  1775.       {
  1776.         /* We've reached the end of this frame.
  1777.            Which other frames are acceptable?  */
  1778.         tem = WINDOW_FRAME (XWINDOW (window));
  1779.  
  1780.         if (! NILP (all_frames))
  1781.           {
  1782.         Lisp_Object tem1;
  1783.  
  1784.         tem1 = tem;
  1785.         tem = next_frame (tem, all_frames);
  1786.         /* In the case where the minibuffer is active,
  1787.            and we include its frame as well as the selected one,
  1788.            next_frame may get stuck in that frame.
  1789.            If that happens, go back to the selected frame
  1790.            so we can complete the cycle.  */
  1791.         if (EQ (tem, tem1))
  1792.           XSETFRAME (tem, selected_frame ());
  1793.           }
  1794.  
  1795.         tem = FRAME_ROOT_WINDOW (XFRAME (tem));
  1796.         break;
  1797.       }
  1798.  
  1799.       window = tem;
  1800.  
  1801.       /* If we're in a combination window, find its first child and
  1802.      recurse on that.  Otherwise, we've found the window we want.  */
  1803.       while (1)
  1804.     {
  1805.       if (!NILP (XWINDOW (window)->hchild))
  1806.         window = XWINDOW (window)->hchild;
  1807.       else if (!NILP (XWINDOW (window)->vchild))
  1808.         window = XWINDOW (window)->vchild;
  1809.       else break;
  1810.     }
  1811.     }
  1812.   /* Which windows are acceptible?
  1813.      Exit the loop and accept this window if
  1814.      this isn't a minibuffer window, or
  1815.      we're accepting minibuffer windows, or
  1816.      we've come all the way around and we're back at the original window.  */
  1817.   while (MINI_WINDOW_P (XWINDOW (window))
  1818.      && ! EQ (minibuf, Qt)
  1819.      && ! EQ (window, start_window));
  1820.  
  1821.   return window;
  1822. }
  1823.  
  1824. DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 4, 0,
  1825.   "Return the window preceeding WINDOW in canonical ordering of windows.\n\
  1826. If omitted, WINDOW defaults to the selected window.\n\
  1827. \n\
  1828. Optional second arg MINIBUF t means count the minibuffer window even\n\
  1829. if not active.  MINIBUF nil or omitted means count the minibuffer iff\n\
  1830. it is active.  MINIBUF neither t nor nil means not to count the\n\
  1831. minibuffer even if it is active.\n\
  1832. \n\
  1833. Several frames may share a single minibuffer; if the minibuffer\n\
  1834. counts, all windows on all frames that share that minibuffer count\n\
  1835. too.  Therefore, `previous-window' can be used to iterate through\n\
  1836. the set of windows even when the minibuffer is on another frame.  If\n\
  1837. the minibuffer does not count, only windows from WINDOW's frame count\n\
  1838. \n\
  1839. Optional third arg ALL-FRAMES t means include windows on all frames.\n\
  1840. ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
  1841. above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
  1842. ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
  1843. Anything else means restrict to WINDOW's frame.\n\
  1844. \n\
  1845. If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
  1846. `previous-window' to iterate through the entire cycle of acceptable\n\
  1847. windows, eventually ending up back at the window you started with.\n\
  1848. `next-window' traverses the same cycle, in the reverse order.")
  1849.      (window, minibuf, all_frames, ignored)
  1850.      Lisp_Object window, minibuf, all_frames, ignored;
  1851. {
  1852.   Lisp_Object tem;
  1853.   Lisp_Object start_window;
  1854.  
  1855.   if (NILP (window))
  1856.     window = Fselected_window (Qnil);
  1857.   else
  1858.     CHECK_LIVE_WINDOW (window, 0);
  1859.  
  1860.   start_window = window;
  1861.  
  1862.   /* minibuf == nil may or may not include minibuffers.
  1863.      Decide if it does.  */
  1864.   if (NILP (minibuf))
  1865.     minibuf = (minibuf_level ? Qt : Qlambda);
  1866.  
  1867. #if 0 /* #### old code, not in FSF.  Probably should be deleted. */
  1868.   if (EQ (mini, Qt)
  1869.       || (! NILP (mini) && minibuf_level))
  1870.     {
  1871.       if (FRAMEP (Vdefault_minibuffer_frame))
  1872.     all_frames = Qt;
  1873.     }
  1874. #endif
  1875.  
  1876.   /* all_frames == nil doesn't specify which frames to include.
  1877.      Decide which frames it includes.  */
  1878.   if (NILP (all_frames))
  1879.     all_frames = (EQ (minibuf, Qt)
  1880.           ? (FRAME_MINIBUF_WINDOW
  1881.              (XFRAME
  1882.               (WINDOW_FRAME
  1883.                (XWINDOW (window)))))
  1884.           : Qnil);
  1885.   else if (EQ (all_frames, Qvisible))
  1886.     ;
  1887.   else if (EQ (all_frames, Qzero))
  1888.     ;
  1889.   else if (! EQ (all_frames, Qt))
  1890.     all_frames = Qnil;
  1891.   /* Now all_frames is t meaning search all frames,
  1892.      nil meaning search just current frame,
  1893.      visible meaning search just visible frames,
  1894.      0 meaning search visible and iconified frames,
  1895.      or a window, meaning search the frame that window belongs to.  */
  1896.  
  1897.   /* Do this loop at least once, to get the next window, and perhaps
  1898.      again, if we hit the minibuffer and that is not acceptable.  */
  1899.   do
  1900.     {
  1901.       /* Find a window that actually has a next one.  This loop
  1902.      climbs up the tree.  */
  1903.       while (tem = XWINDOW (window)->prev, NILP (tem))
  1904.     if (tem = XWINDOW (window)->parent, !NILP (tem))
  1905.       window = tem;
  1906.         else  /* window must be minibuffer window now */
  1907.       {
  1908.         /* We have found the top window on the frame.
  1909.            Which frames are acceptable?  */
  1910.         tem = WINDOW_FRAME (XWINDOW (window));
  1911.  
  1912.         if (! NILP (all_frames))
  1913.           /* It's actually important that we use prev_frame here,
  1914.          rather than next_frame.  All the windows acceptable
  1915.          according to the given parameters should form a ring;
  1916.          Fnext_window and Fprevious_window should go back and
  1917.          forth around the ring.  If we use next_frame here,
  1918.          then Fnext_window and Fprevious_window take different
  1919.          paths through the set of acceptable windows.
  1920.          window_loop assumes that these `ring' requirement are
  1921.          met.  */
  1922.           {
  1923.         Lisp_Object tem1;
  1924.  
  1925.         tem1 = tem;
  1926.         tem = prev_frame (tem, all_frames);
  1927.         /* In the case where the minibuffer is active,
  1928.            and we include its frame as well as the selected one,
  1929.            next_frame may get stuck in that frame.
  1930.            If that happens, go back to the selected frame
  1931.            so we can complete the cycle.  */
  1932.         if (EQ (tem, tem1))
  1933.           XSETFRAME (tem, selected_frame ());
  1934.           }
  1935.  
  1936.         /* If this frame has a minibuffer, find that window first,
  1937.            because it is conceptually the last window in that frame.  */
  1938.         if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
  1939.           tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
  1940.         else
  1941.           tem = FRAME_ROOT_WINDOW (XFRAME (tem));
  1942.  
  1943.         break;
  1944.       }
  1945.  
  1946.       window = tem;
  1947.  
  1948.       /* If we're in a combination window, find its first child and
  1949.      recurse on that.  Otherwise, we've found the window we want.  */
  1950.       while (1)
  1951.     {
  1952.       if (!NILP (XWINDOW (window)->hchild))
  1953.         window = XWINDOW (window)->hchild;
  1954.       else if (!NILP (XWINDOW (window)->vchild))
  1955.         window = XWINDOW (window)->vchild;
  1956.       else break;
  1957.       while (tem = XWINDOW (window)->next, !NILP (tem))
  1958.         window = tem;
  1959.     }
  1960.     }
  1961.   /* Which windows are acceptible?
  1962.      Exit the loop and accept this window if
  1963.      this isn't a minibuffer window, or
  1964.      we're accepting minibuffer windows, or
  1965.      we've come all the way around and we're back at the original window.  */
  1966.   while (MINI_WINDOW_P (XWINDOW (window))
  1967.      && ! EQ (minibuf, Qt)
  1968.      && ! EQ (window, start_window));
  1969.  
  1970.   return window;
  1971. }
  1972.  
  1973. DEFUN ("next-vertical-window", Fnext_vertical_window, Snext_vertical_window,
  1974.        0, 1, 0,
  1975.   "Return the next window which is vertically after WINDOW.\n")
  1976.   (window)
  1977.     Lisp_Object window;
  1978. {
  1979.   Lisp_Object root;
  1980.   struct window *w = decode_window (window);
  1981.   XSETWINDOW (window, w);
  1982.  
  1983.   if (MINI_WINDOW_P (XWINDOW (window)))
  1984.     return Qnil;
  1985.  
  1986.   root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
  1987.  
  1988.   if (EQ (window, root))
  1989.     {
  1990.       while (1)
  1991.     if (!NILP (XWINDOW (window)->hchild))
  1992.       window = XWINDOW (window)->hchild;
  1993.     else if (!NILP (XWINDOW (window)->vchild))
  1994.       window = XWINDOW (window)->vchild;
  1995.     else
  1996.       return window;
  1997.     }
  1998.  
  1999.   do
  2000.     {
  2001.       if (!NILP (XWINDOW (window)->parent) &&
  2002.       !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
  2003.     {
  2004.       if (!NILP (XWINDOW (window)->next))
  2005.         return XWINDOW (window)->next;
  2006.       else
  2007.         window = XWINDOW (window)->parent;
  2008.     }
  2009.       else
  2010.     window = XWINDOW (window)->parent;
  2011.     }
  2012.   while (!EQ (window, root));
  2013.  
  2014.   while (1)
  2015.     if (!NILP (XWINDOW (window)->hchild))
  2016.       window = XWINDOW (window)->hchild;
  2017.     else if (!NILP (XWINDOW (window)->vchild))
  2018.       window = XWINDOW (window)->vchild;
  2019.     else
  2020.       return window;
  2021. }
  2022.  
  2023. DEFUN ("other-window", Fother_window, Sother_window, 1, 3, "p",
  2024.   "Select the N'th different window on this frame.\n\
  2025. All windows on current frame are arranged in a cyclic order.\n\
  2026. This command selects the window N steps away in that order.\n\
  2027. A negative N moves in the opposite order.\n\
  2028. \n\
  2029. If optional argument FRAME is `visible', search all visible frames.\n\
  2030. If FRAME is 0, search all visible and iconified frames.\n\
  2031. If FRAME is t, search all frames.\n\
  2032. If FRAME is nil, search only the selected frame.\n\
  2033. If FRAME is a frame, search only that frame.")
  2034.   (n, frame, ignored)
  2035.      Lisp_Object n, frame, ignored;
  2036. {
  2037.   int i;
  2038.   Lisp_Object w;
  2039.  
  2040.   CHECK_INT (n, 0);
  2041.   w = Fselected_window (Qnil);
  2042.   i = XINT (n);
  2043.  
  2044.   while (i > 0)
  2045.     {
  2046.       w = Fnext_window (w, Qnil, frame, Qnil);
  2047.       i--;
  2048.     }
  2049.   while (i < 0)
  2050.     {
  2051.       w = Fprevious_window (w, Qnil, frame, Qnil);
  2052.       i++;
  2053.     }
  2054.   Fselect_window (w);
  2055.   return Qnil;
  2056. }
  2057.  
  2058.  
  2059. /* Look at all windows, performing an operation specified by TYPE
  2060.    with argument OBJ.
  2061.  
  2062.    If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
  2063.    frame.  If FRAMES is a frame, just look at windows on that frame.
  2064.    If MINI is non-zero, perform the operation on minibuffer windows too.
  2065. */
  2066.  
  2067. enum window_loop
  2068. {
  2069.   WINDOW_LOOP_UNUSED,
  2070.   GET_BUFFER_WINDOW,        /* Arg is buffer */
  2071.   GET_LRU_WINDOW,        /* Arg is t for full-width windows only */
  2072.   DELETE_OTHER_WINDOWS,        /* Arg is window not to delete */
  2073.   DELETE_BUFFER_WINDOWS,    /* Arg is buffer */
  2074.   GET_LARGEST_WINDOW,
  2075.   UNSHOW_BUFFER,        /* Arg is buffer */
  2076.   GET_BUFFER_WINDOW_COUNT,    /* Arg is buffer */
  2077.   GET_BUFFER_MRU_WINDOW        /* Arg is buffer */
  2078. };
  2079.  
  2080. static Lisp_Object
  2081. window_loop (enum window_loop type,
  2082.              Lisp_Object obj, 
  2083.              int mini,
  2084.              Lisp_Object frames,
  2085.          int dedicated_too)
  2086. {
  2087.   /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
  2088.   Lisp_Object w;
  2089.   Lisp_Object best_window;
  2090.   Lisp_Object next_window;
  2091.   Lisp_Object last_window;
  2092.   struct frame *frame, *sel_frame;
  2093.   Lisp_Object frame_arg = Qt;
  2094.   int count = 0;        /* for GET_BUFFER_WINDOW_COUNT */
  2095.   /* #### I think the change of "precomputing" last_window and next_window
  2096.    * ####  catch the lossage this is meant(?) to punt on...
  2097.    */
  2098.   int lose_lose = 0; 
  2099.   Lisp_Object dev;
  2100.  
  2101.   DEVICE_LOOP (dev)
  2102.     {
  2103.       if (NILP (DEVICE_SELECTED_FRAME (XDEVICE (XCAR (dev)))))
  2104.     continue;
  2105.       else
  2106.     sel_frame = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (XCAR (dev))));
  2107.  
  2108.       /* If we're only looping through windows on a particular frame,
  2109.      frame points to that frame.  If we're looping through windows
  2110.      on all frames, frame is 0.  */
  2111.       if (FRAMEP (frames))
  2112.     frame = XFRAME (frames);
  2113.       else if (NILP (frames))
  2114.     frame = sel_frame;
  2115.       else
  2116.     frame = 0;
  2117.       if (frame)
  2118.     frame_arg = Qlambda;
  2119.       else if (EQ (frames, Qzero))
  2120.     frame_arg = frames;
  2121.       else if (EQ (frames, Qvisible))
  2122.     frame_arg = frames;
  2123.  
  2124.       /* frame_arg is Qlambda to stick to one frame,
  2125.      Qvisible to consider all visible frames,
  2126.      or Qt otherwise.  */
  2127.  
  2128.       /* Pick a window to start with.  */
  2129.       if (WINDOWP (obj))
  2130.     w = obj;
  2131.       else if (frame)
  2132.     w = FRAME_SELECTED_WINDOW (frame);
  2133.       else
  2134.     w = FRAME_SELECTED_WINDOW (sel_frame);
  2135.  
  2136.       /* Figure out the last window we're going to mess with.  Since
  2137.      Fnext_window, given the same options, is guaranteed to go in a
  2138.      ring, we can just use Fprevious_window to find the last one.
  2139.  
  2140.      We can't just wait until we hit the first window again,
  2141.      because it might be deleted.  */
  2142.  
  2143.       last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qnil);
  2144.  
  2145.       best_window = Qnil;
  2146.       for (;;)
  2147.     {
  2148.       struct window *p = XWINDOW (w);
  2149.       struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
  2150.  
  2151.       /* Pick the next window now, since some operations will delete
  2152.          the current window.  */
  2153.       next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qnil);
  2154.  
  2155.       /* #### Still needed ?? */
  2156.       /* Given the outstanding quality of the rest of this code, 
  2157.          I feel no shame about putting this piece of shit in. */
  2158.       if (++lose_lose >= 500)
  2159.         return Qnil;
  2160.  
  2161.       /* Note that we do not pay attention here to whether
  2162.          the frame is visible, since Fnext_window skips non-visible frames
  2163.          if that is desired, under the control of frame_arg.  */
  2164.       if (! MINI_WINDOW_P (p)
  2165.           || (mini && minibuf_level > 0))
  2166.         switch (type)
  2167.           {
  2168.           case GET_BUFFER_WINDOW:
  2169.         {
  2170.           if (XBUFFER (p->buffer) == XBUFFER (obj))
  2171.             return w;
  2172.           break;
  2173.         }
  2174.  
  2175.           case GET_BUFFER_WINDOW_COUNT:
  2176.         {
  2177.           if (XBUFFER (p->buffer) == XBUFFER (obj))
  2178.             count++;
  2179.           break;
  2180.         }
  2181.  
  2182.           case GET_LRU_WINDOW:
  2183.         {
  2184.           /* t as arg means consider only full-width windows */
  2185.           if (!NILP (obj)
  2186.               && window_char_width (p, 0) != FRAME_WIDTH (w_frame))
  2187.             break;
  2188.           /* Ignore dedicated windows and minibuffers.  */
  2189.           if (MINI_WINDOW_P (p)
  2190.               || (dedicated_too ? 0 : !NILP (p->dedicated)))
  2191.             break;
  2192.           if (NILP (best_window)
  2193.               || (XINT (XWINDOW (best_window)->use_time)
  2194.               > XINT (p->use_time)))
  2195.             best_window = w;
  2196.           break;
  2197.         }
  2198.  
  2199.           case GET_BUFFER_MRU_WINDOW:
  2200.         {
  2201.           /* #### what about the first check in GET_LRU_WINDOW? */
  2202.           /* Ignore dedicated windows and minibuffers. */
  2203.           if (MINI_WINDOW_P (p)
  2204.               || (dedicated_too ? 0 : !NILP (p->dedicated)))
  2205.             break;
  2206.  
  2207.           if (XBUFFER (p->buffer) == XBUFFER (obj))
  2208.             {
  2209.               if (NILP (best_window)
  2210.               || (XINT (XWINDOW (best_window)->use_time)
  2211.                   < XINT (p->use_time)))
  2212.             best_window = w;
  2213.             }
  2214.           break;
  2215.         }
  2216.  
  2217.           case DELETE_OTHER_WINDOWS:
  2218.         {
  2219.           /* Don't delete the last window on a frame; this can
  2220.              happen when the minibuffer is selected, and would
  2221.              cause the frame to be deleted. */
  2222.           if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
  2223.             Fdelete_window (w);
  2224.           break;
  2225.         }
  2226.  
  2227.           case DELETE_BUFFER_WINDOWS:
  2228.         {
  2229.           if (EQ (p->buffer, obj))
  2230.             {
  2231.               /* If we're deleting the buffer displayed in the
  2232.              only window on the frame, find a new buffer
  2233.              to display there.  */
  2234.               if (NILP (p->parent))
  2235.             {
  2236.               Lisp_Object new_buffer =
  2237.                 Fother_buffer (obj, Qnil, Qnil);
  2238.               if (NILP (new_buffer))
  2239.                 new_buffer =
  2240.                   Fget_buffer_create (QSscratch);
  2241.               Fset_window_buffer (w, new_buffer);
  2242.               if (EQ (w, Fselected_window (Qnil)))
  2243.                 Fset_buffer (p->buffer);
  2244.             }
  2245.               else
  2246.             Fdelete_window (w);
  2247.             }
  2248.           break;
  2249.         }
  2250.  
  2251.           case GET_LARGEST_WINDOW:
  2252.         {
  2253.           /* Ignore dedicated windows and minibuffers.  */
  2254.           if (MINI_WINDOW_P (p)
  2255.               || (dedicated_too ? 0 : !NILP (p->dedicated)))
  2256.             break;
  2257.           {
  2258.             /* write the check as follows to avoid tripping
  2259.                error_check_window() --ben */
  2260.             struct window *b = NILP (best_window) ? 0 :
  2261.               XWINDOW (best_window);
  2262.             if (NILP (best_window)
  2263.             || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
  2264.                 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
  2265.               best_window = w;
  2266.           }
  2267.           break;
  2268.         }
  2269.  
  2270.           case UNSHOW_BUFFER:
  2271.         {
  2272.           if (EQ (p->buffer, obj))
  2273.             {
  2274.               /* Find another buffer to show in this window.  */
  2275.               Lisp_Object another_buffer =
  2276.             Fother_buffer (obj, Qnil, Qnil);
  2277.               if (NILP (another_buffer))
  2278.             another_buffer
  2279.               = Fget_buffer_create (QSscratch);
  2280.               /* If this window is dedicated, and in a frame
  2281.              of its own, kill the frame.  */
  2282.               if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
  2283.               && !NILP (p->dedicated)
  2284.               && other_visible_frames (w_frame))
  2285.             {
  2286.               /* Skip the other windows on this frame.
  2287.                  There might be one, the minibuffer!  */
  2288.               if (! EQ (w, last_window))
  2289.                 while (w_frame == XFRAME (WINDOW_FRAME
  2290.                               (XWINDOW (next_window))))
  2291.                   {
  2292.                 /* As we go, check for the end of the
  2293.                    loop.  We mustn't start going
  2294.                    around a second time.  */
  2295.                 if (EQ (next_window, last_window))
  2296.                   {
  2297.                     last_window = w;
  2298.                     break;
  2299.                   }
  2300.                 next_window = Fnext_window (next_window,
  2301.                                 mini ? Qt : Qnil,
  2302.                                 frame_arg, Qnil);
  2303.                   }
  2304.               /* Now we can safely delete the frame.  */
  2305.               delete_frame_internal (WINDOW_FRAME (p), 0);
  2306.             }
  2307.               else
  2308.             {
  2309.               /* Otherwise show a different buffer in the
  2310.                              window.  */
  2311.               p->dedicated = Qnil;
  2312.               Fset_window_buffer (w, another_buffer);
  2313.               if (EQ (w, Fselected_window (Qnil)))
  2314.                 Fset_buffer (p->buffer);
  2315.             }
  2316.             }
  2317.           break;
  2318.         }
  2319.  
  2320.           default: 
  2321.         abort ();
  2322.           }
  2323.  
  2324.       if (EQ (w, last_window))
  2325.         break;
  2326.  
  2327.       w = next_window;
  2328.     }
  2329.     }
  2330.  
  2331.   if (type == GET_BUFFER_WINDOW_COUNT)
  2332.     return (make_number (count));
  2333.   else
  2334.     return (best_window);
  2335. }
  2336.  
  2337. /* only display_glyph_in_buffer in xdisp.c is using this at the moment */
  2338. int
  2339. buffer_window_count (struct buffer *b, struct frame *f)
  2340. {
  2341.   Lisp_Object buffer, frame;
  2342.  
  2343.   XSETFRAME (frame, f);
  2344.   XSETBUFFER (buffer, b);
  2345.  
  2346.   return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1));
  2347. }
  2348.  
  2349. /* only display_glyph_in_buffer in xdisp.c is using this at the moment */
  2350. int
  2351. buffer_window_mru (struct window *w)
  2352. {
  2353.   Lisp_Object window = 
  2354.     window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1);
  2355.  
  2356.   if (NILP (window))
  2357.     return 0;
  2358.   else if (XWINDOW (window) == w)
  2359.     return 1;
  2360.   else
  2361.     return 0;
  2362. }
  2363.  
  2364.  
  2365. DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
  2366.   "Return the window least recently selected or used for display.\n\
  2367. If optional argument FRAME is `visible', search all visible frames.\n\
  2368. If FRAME is 0, search all visible and iconified frames.\n\
  2369. If FRAME is t, search all frames.\n\
  2370. If FRAME is nil, search only the selected frame.\n\
  2371. If FRAME is a frame, search only that frame.")
  2372.   (frame)
  2373.     Lisp_Object frame;
  2374. {
  2375.   Lisp_Object w;
  2376.   /* First try for a non-dedicated window that is full-width */
  2377.   w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0);
  2378.   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
  2379.     return w;
  2380.  
  2381.   /* Then try for any non-dedicated window */
  2382.   w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0);
  2383.   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
  2384.     return w;
  2385.  
  2386.   /* then try for a dedicated window that is full-width */
  2387.   w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1);
  2388.   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
  2389.     return w;
  2390.  
  2391.   /* If none of them, then all windows, dedicated or not. */
  2392.   w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1);
  2393.  
  2394.   /* At this point we damn well better have found something. */
  2395.   if (NILP (w)) abort ();
  2396.  
  2397.   return (w);
  2398. }
  2399.  
  2400. DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
  2401.   "Return the window largest in area.\n\
  2402. If optional argument FRAME is `visible', search all visible frames.\n\
  2403. If FRAME is 0, search all visible and iconified frames.\n\
  2404. If FRAME is t, search all frames.\n\
  2405. If FRAME is nil, search only the selected frame.\n\
  2406. If FRAME is a frame, search only that frame.")
  2407.   (frame)
  2408.     Lisp_Object frame;
  2409. {
  2410.   /* Search dedicated windows too (is this sensible?) */
  2411.   return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 1);
  2412. }
  2413.  
  2414. DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 3, 0,
  2415.   "Return a window currently displaying BUFFER, or nil if none.\n\
  2416. If optional argument FRAME is `visible', search all visible frames.\n\
  2417. If optional argument FRAME is 0, search all visible and iconified frames.\n\
  2418. If FRAME is t, search all frames.\n\
  2419. If FRAME is nil, search only the selected frame.\n\
  2420. If FRAME is a frame, search only that frame.")
  2421.   (buffer, frame, ignored)
  2422.     Lisp_Object buffer, frame, ignored;
  2423. {
  2424.   buffer = Fget_buffer (buffer);
  2425.   if (BUFFERP (buffer))
  2426.     /* Search dedicated windows too. */
  2427.     return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1);
  2428.   else
  2429.     return Qnil;
  2430. }
  2431.  
  2432. /* These functions used to be `buffer-left-margin-pixel-width', etc.
  2433.    but there is no sensible way to implement those functions, since
  2434.    you can't in general derive a window from a buffer. */
  2435.  
  2436. DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
  2437.        Swindow_left_margin_pixel_width, 0, 1, 0,
  2438.   "Return the width in pixels of the left outside margin of window WINDOW.\n\
  2439. If WINDOW is nil, the selected window is assumed.")
  2440.   (window)
  2441.     Lisp_Object window;
  2442. {
  2443.   struct window *w = decode_window (window);
  2444.  
  2445.   return (make_number (window_left_margin_width (w)));
  2446. }
  2447.  
  2448. DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
  2449.        Swindow_right_margin_pixel_width, 0, 1, 0,
  2450.   "Return the width in pixels of the right outside margin of window WINDOW.\n\
  2451. If WINDOW is nil, the selected window is assumed.")
  2452.   (window)
  2453.     Lisp_Object window;
  2454. {
  2455.   struct window *w = decode_window (window);
  2456.  
  2457.   return (make_number (window_right_margin_width (w)));
  2458. }
  2459.  
  2460. DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
  2461.   0, 1, "",
  2462.   "Make WINDOW (or the selected window) fill its frame.\n\
  2463. Only the frame WINDOW is on is affected.\n\
  2464. This function tries to reduce display jumps\n\
  2465. by keeping the text previously visible in WINDOW\n\
  2466. in the same place on the frame.  Doing this depends on\n\
  2467. the value of (window-start WINDOW), so if calling this function\n\
  2468. in a program gives strange scrolling, make sure the window-start\n\
  2469. value is reasonable when this function is called.")
  2470.   (window)
  2471.      Lisp_Object window;
  2472. {
  2473.   struct window *w = decode_window (window);
  2474.   struct buffer *b = XBUFFER (w->buffer);
  2475.   Bufpos start_pos;
  2476.   int old_top = WINDOW_TOP (w);
  2477.  
  2478.   XSETWINDOW (window, w);
  2479.  
  2480.   /* Ignore dedicated windows. */
  2481.   window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0);
  2482.  
  2483.   start_pos = marker_position (w->start[CURRENT_DISP]);
  2484.  
  2485.   /* Try to minimize scrolling, by setting the window start to the
  2486.      point which will cause the text at the old window start to be at
  2487.      the same place on the frame.  But don't try to do this if the
  2488.      window start is outside the visible portion (as might happen when
  2489.      the display is not current, due to typeahead). */
  2490.   if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
  2491.       && !MINI_WINDOW_P (w))
  2492.     {
  2493.       Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
  2494.  
  2495.       if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
  2496.     {
  2497.       Fset_marker (w->start[CURRENT_DISP], make_number (new_start),
  2498.                w->buffer);
  2499.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  2500.     }
  2501.     }
  2502.  
  2503.   return Qnil;
  2504. }
  2505.  
  2506. DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
  2507.   1, 2, "bDelete windows on (buffer): ",
  2508.   "Delete all windows showing BUFFER.\n\
  2509. Optional second argument FRAME controls which frames are affected.\n\
  2510. If nil or omitted, delete all windows showing BUFFER in any frame.\n\
  2511. If t, delete only windows showing BUFFER in the selected frame.\n\
  2512. If `visible', delete all windows showing BUFFER in any visible frame.\n\
  2513. If a frame, delete only windows showing BUFFER in that frame.")
  2514.      (buffer, frame)
  2515.      Lisp_Object buffer, frame;
  2516. {
  2517.   /* This function can GC */
  2518.   /* FRAME uses t and nil to mean the opposite of what window_loop
  2519.      expects. */
  2520.   if (!FRAMEP (frame))
  2521.     frame = NILP (frame) ? Qt : Qnil;
  2522.  
  2523.   if (!NILP (buffer))
  2524.     {
  2525.       buffer = Fget_buffer (buffer);
  2526.       CHECK_BUFFER (buffer, 0);
  2527.       /* Ignore dedicated windows. */
  2528.       window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0);
  2529.     }
  2530.   return Qnil;
  2531. }
  2532.  
  2533. DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
  2534.   Sreplace_buffer_in_windows,
  2535.   1, 1, "bReplace buffer in windows: ",
  2536.   "Replace BUFFER with some other buffer in all windows showing it.")
  2537.   (buffer)
  2538.      Lisp_Object buffer;
  2539. {
  2540.   /* This function can GC */
  2541.   if (!NILP (buffer))
  2542.     {
  2543.       buffer = Fget_buffer (buffer);
  2544.       CHECK_BUFFER (buffer, 0);
  2545.       /* Ignore dedicated windows. */
  2546.       window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0);
  2547.     }
  2548.   return Qnil;
  2549. }
  2550.  
  2551. /* The smallest acceptable dimensions for a window.  Anything smaller
  2552.    might crash Emacs.  */
  2553. #define MIN_SAFE_WINDOW_WIDTH  (2)
  2554. #define MIN_SAFE_WINDOW_HEIGHT (2)
  2555.  
  2556. /* Make sure that window_min_height and window_min_width are
  2557.    not too small; if they are, set them to safe minima.  */
  2558.  
  2559. static void
  2560. check_min_window_sizes (void)
  2561. {
  2562.   /* Smaller values might permit a crash.  */
  2563.   if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
  2564.     window_min_width = MIN_SAFE_WINDOW_WIDTH;
  2565.   if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
  2566.     window_min_height = MIN_SAFE_WINDOW_HEIGHT;
  2567. }
  2568.  
  2569. /* If *ROWS or *COLS are too small a size for FRAME, set them to the
  2570.    minimum allowable size.  */
  2571. void
  2572. check_frame_size (struct frame *frame, int *rows, int *cols)
  2573. {
  2574.   /* For height, we have to see whether the frame has a minibuffer, and
  2575.      whether it wants a modeline.  */
  2576.   int min_height = ((FRAME_MINIBUF_ONLY_P (frame)
  2577.                      || ! FRAME_HAS_MINIBUF_P (frame))
  2578.                     ? MIN_SAFE_WINDOW_HEIGHT
  2579.                     : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
  2580.  
  2581.   if (*rows < min_height)
  2582.     *rows = min_height;
  2583.   if (*cols  < MIN_SAFE_WINDOW_WIDTH)
  2584.     *cols = MIN_SAFE_WINDOW_WIDTH;
  2585. }
  2586.  
  2587. /* Normally the window is deleted if it gets too small.
  2588.    nodelete nonzero means do not do this.
  2589.    (The caller should check later and do so if appropriate)  */
  2590. static void
  2591. set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
  2592.             int set_height)
  2593. {
  2594.   struct window *w = XWINDOW (window);
  2595.   struct frame *f = XFRAME (w->frame);
  2596.   struct window *c;
  2597.   int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
  2598.   Lisp_Object child, minor_kid, major_kid;
  2599.   int minsize;
  2600.   int line_size;
  2601.   int defheight, defwidth;
  2602.  
  2603.   /* #### This is very likely incorrect and instead the char_to_pixel_
  2604.      functions should be called. */
  2605.   default_face_height_and_width (window, &defheight, &defwidth);
  2606.   line_size = (set_height ? defheight : defwidth);
  2607.  
  2608.   minsize = (set_height ? window_min_height : window_min_width);
  2609.   minsize *= line_size;
  2610.  
  2611.   check_min_window_sizes ();
  2612.  
  2613.   if (!nodelete
  2614.       && !TOP_LEVEL_WINDOW_P (w)
  2615.       && new_pixsize < minsize)
  2616.     {
  2617.       Fdelete_window (window);
  2618.       return;
  2619.     }
  2620.  
  2621.   SET_LAST_MODIFIED (w, 0);
  2622.   SET_LAST_FACECHANGE (w);
  2623.   MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);    /* multiple windows affected */
  2624.   if (set_height)
  2625.     {
  2626.       WINDOW_HEIGHT (w) = new_pixsize;
  2627.       major_kid = w->vchild;
  2628.       minor_kid = w->hchild;
  2629.     }
  2630.   else
  2631.     {
  2632.       WINDOW_WIDTH (w) = new_pixsize;
  2633.       major_kid = w->hchild;
  2634.       minor_kid = w->vchild;
  2635.     }
  2636.  
  2637.   if (!NILP (minor_kid))
  2638.     {
  2639.       for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
  2640.     {
  2641.       if (set_height)
  2642.         WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
  2643.       else
  2644.         WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
  2645.  
  2646.       set_window_pixsize (child, new_pixsize, nodelete, set_height);
  2647.     }
  2648.     }
  2649.   else if (!NILP (major_kid))
  2650.     {
  2651.       int last_pos, last_old_pos, pos, old_pos, first;
  2652.       int pixel_adj_left = new_pixsize - old_pixsize;
  2653.       int div_val = old_pixsize << 1;
  2654.  
  2655.       /* Sometimes we may get called with our old size.  In that case
  2656.          we don't need to do anything. */
  2657.       if (!pixel_adj_left)
  2658.     return;
  2659.  
  2660.       last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
  2661.       last_old_pos = 0;
  2662.  
  2663.       for (child = major_kid; !NILP (child); child = c->next)
  2664.     {
  2665.       c = XWINDOW (child);
  2666.  
  2667.       if (set_height)
  2668.         {
  2669.           old_pos = last_old_pos + WINDOW_HEIGHT (c);
  2670.           WINDOW_TOP (c) = last_pos;
  2671.         }
  2672.       else
  2673.         {
  2674.           old_pos = last_old_pos + WINDOW_WIDTH (c);
  2675.           WINDOW_LEFT (c) = last_pos;
  2676.         }
  2677.  
  2678.       pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
  2679.       /* All but the the last window should have a height which is
  2680.              a multiple of the default line height. */
  2681.       if (!NILP (c->next))
  2682.         pos = (pos / line_size) * line_size;
  2683.  
  2684.       /* Avoid confusion: don't delete child if it becomes too small */
  2685.       set_window_pixsize (child, pos + first - last_pos, 1, set_height);
  2686.  
  2687.       last_pos = pos + first;
  2688.       last_old_pos = old_pos;
  2689.     }
  2690.  
  2691.       /* Now delete any children that became too small.  */
  2692.       if (!nodelete)
  2693.     for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
  2694.       {
  2695.         if (set_height)
  2696.           set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
  2697.         else
  2698.           set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
  2699.       }
  2700.     }
  2701. }
  2702.  
  2703. /* Set the height of WINDOW and all its inferiors.  */
  2704. void
  2705. set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
  2706. {
  2707.   set_window_pixsize (window, new_pixheight, nodelete, 1);
  2708. }
  2709.  
  2710. /* Recursively set width of WINDOW and its inferiors. */
  2711. void
  2712. set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
  2713. {
  2714.   set_window_pixsize (window, new_pixwidth, nodelete, 0);
  2715. }
  2716.  
  2717.  
  2718. static int window_select_count;
  2719.  
  2720. DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
  2721.   "Make WINDOW display BUFFER as its contents.\n\
  2722. BUFFER can be a buffer or buffer name.")
  2723.   (window, buffer)
  2724.      Lisp_Object window, buffer;
  2725. {
  2726.   Lisp_Object tem;
  2727.   struct window *w = decode_window (window);
  2728.  
  2729.   buffer = Fget_buffer (buffer);
  2730.   CHECK_BUFFER (buffer, 1);
  2731.  
  2732.   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
  2733.     error ("Attempt to display deleted buffer");
  2734.  
  2735.   tem = w->buffer;
  2736.   if (NILP (tem))
  2737.     error ("Window is deleted");
  2738.  
  2739.   /* While this seems like a logical thing to do, it causes problems
  2740.      because of saved window configurations.  It is possible for a
  2741.      buffer to get restored into a window in which it is already being
  2742.      displayed, but start and point are actually at completely
  2743.      different locations.  So we let this function complete fully and
  2744.      it will then make sure redisplay correctly updates things. */
  2745. #if 0
  2746.   else if (EQ (tem, buffer))
  2747.     return (Qnil);
  2748. #endif
  2749.   else if (! EQ (tem, Qt))    /* w->buffer is t when the window
  2750.                    is first being set up.  */
  2751.     {
  2752.       if (!NILP (w->dedicated) && !EQ (tem, buffer))
  2753.     error ("Window is dedicated to buffer %s",
  2754.            string_data (XSTRING (XBUFFER (tem)->name)));
  2755.  
  2756.       unshow_buffer (w);
  2757.     }
  2758.  
  2759.   w->buffer = buffer;
  2760.   w->window_end_pos[CURRENT_DISP] = 0;
  2761.   w->hscroll = 0;;
  2762.   Fset_marker (w->pointm[CURRENT_DISP],
  2763.            make_number (BUF_PT (XBUFFER (buffer))),
  2764.            buffer);
  2765.   set_marker_restricted (w->start[CURRENT_DISP],
  2766.              make_number (XBUFFER (buffer)->last_window_start),
  2767.              buffer);
  2768.   Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
  2769.   w->start_at_line_beg = 0;
  2770.   w->force_start = 0;           /* Lucid fix */
  2771.   SET_LAST_MODIFIED (w, 1);
  2772.   SET_LAST_FACECHANGE (w);
  2773.   MARK_WINDOWS_CHANGED (w);
  2774.   recompute_all_cached_specifiers_in_window (w);
  2775.   if (EQ (window, Fselected_window (Qnil)))
  2776.     {
  2777.       Fset_buffer (buffer);
  2778. #ifdef ENERGIZE
  2779.       energize_buffer_shown_hook (w);
  2780. #endif
  2781.     }
  2782.   return Qnil;
  2783. }
  2784.  
  2785. DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
  2786.   "Select WINDOW.  Most editing will apply to WINDOW's buffer.\n\
  2787. The main editor command loop selects the buffer of the selected window\n\
  2788. before each command.")
  2789.   (window)
  2790.      Lisp_Object window;
  2791. {
  2792.   struct window *w;
  2793.   Lisp_Object old_selected_window = Fselected_window (Qnil);
  2794.   
  2795.   CHECK_LIVE_WINDOW (window, 0);
  2796.   w = XWINDOW (window);
  2797.  
  2798.   /* we have already caught dead-window errors */
  2799.   if (!NILP (w->hchild) || !NILP (w->vchild))
  2800.     error ("Trying to select non-leaf window");
  2801.  
  2802.   w->use_time = make_number (++window_select_count);
  2803.   if (EQ (window, old_selected_window))
  2804.     return window;
  2805.  
  2806.   /* deselect the old window, if it exists (it might not exist if
  2807.      the selected device has no frames, which occurs at startup) */
  2808.   if (!NILP (old_selected_window))
  2809.     {
  2810.       struct window *ow = XWINDOW (old_selected_window);
  2811.  
  2812. #ifdef ENERGIZE
  2813.       if (! MINI_WINDOW_P (w))
  2814.     energize_window_deselected_hook (ow);
  2815. #endif
  2816.  
  2817.       Fset_marker (ow->pointm[CURRENT_DISP],
  2818.            make_number (BUF_PT (XBUFFER (ow->buffer))),
  2819.            ow->buffer);
  2820.  
  2821.       MARK_WINDOWS_CHANGED (ow);
  2822.     }
  2823.  
  2824.   /* now select the window's frame */
  2825.   FRAME_SELECTED_WINDOW (XFRAME (WINDOW_FRAME (w))) = window;
  2826.   select_frame_1 (WINDOW_FRAME (w));
  2827.  
  2828.   /* also select the window's buffer */
  2829.   record_buffer (w->buffer);
  2830.   Fset_buffer (w->buffer);
  2831.  
  2832.   /* Go to the point recorded in the window.
  2833.      This is important when the buffer is in more
  2834.      than one window.  It also matters when
  2835.      redisplay_window has altered point after scrolling,
  2836.      because it makes the change only in the window.  */
  2837.   {
  2838.     Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
  2839.     if (new_point < BUF_BEGV (current_buffer))
  2840.       new_point = BUF_BEGV (current_buffer);
  2841.     else if (new_point > BUF_ZV (current_buffer))
  2842.       new_point = BUF_ZV (current_buffer);
  2843.  
  2844.     BUF_SET_PT (current_buffer, new_point);
  2845.   }
  2846.  
  2847.   MARK_WINDOWS_CHANGED (w);
  2848.  
  2849. #ifdef ENERGIZE
  2850.   if (! MINI_WINDOW_P (w))
  2851.     energize_window_selected_hook (w);
  2852. #endif
  2853.  
  2854.   return window;
  2855. }
  2856.  
  2857. /* #### This function is not synched up with FSF 19.28.  There's lots
  2858.    of added junk (`special-display-buffer-names' etc.) that I haven't looked
  2859.    into to determine whether it's crockish or not, so I'm leaving this
  2860.    alone.  --ben */
  2861.  
  2862. DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
  2863.        "BDisplay buffer:\nP",
  2864.   "Make BUFFER appear in some window on the current frame, but don't\n\
  2865. select it.\n\
  2866. BUFFER can be a buffer or a buffer name.\n\
  2867. If BUFFER is shown already in some window in the current frame,\n\
  2868. just uses that one, unless the window is the selected window and\n\
  2869. NOT-THIS-WINDOW-P is non-nil (interactively, with prefix arg).\n\
  2870. \n\
  2871. If BUFFER has a dedicated frame, display on that frame instead of\n\
  2872. the current frame, unless OVERRIDE-FRAME is non-nil.\n\
  2873. \n\
  2874. If OVERRIDE-FRAME is non-nil, display on that frame instead of\n\
  2875. the current frame (or the dedicated frame).\n\
  2876. \n\
  2877. If `pop-up-windows' is non-nil, always use the\n\
  2878. current frame and create a new window regardless of whether the\n\
  2879. buffer has a dedicated frame, and regardless of whether\n\
  2880. OVERRIDE-FRAME was specified.\n\
  2881. \n\
  2882. Returns the window displaying BUFFER.")
  2883.   (buffer, not_this_window_p, override_frame)
  2884.   Lisp_Object buffer, not_this_window_p, override_frame;
  2885. {
  2886.   /* This function can GC */
  2887.   Lisp_Object window;
  2888.   Lisp_Object old_frame, target_frame;
  2889.  
  2890.   old_frame = Fselected_frame (Qnil);
  2891.  
  2892.   buffer = Fget_buffer (buffer);
  2893.   CHECK_BUFFER (buffer, 0);
  2894.  
  2895.   target_frame = old_frame;
  2896.  
  2897.   if (!NILP (Vpre_display_buffer_function))
  2898.     {
  2899.       struct gcpro gcpro1, gcpro2, gcpro3;
  2900.       /* No need to gcpro target_frame, since GC doesn't relocate */
  2901.       GCPRO3 (buffer, not_this_window_p, override_frame);
  2902.       call3 (Vpre_display_buffer_function,
  2903.          buffer, not_this_window_p, override_frame);
  2904.       UNGCPRO;
  2905.       /* this hook may have selected some other frame, so take notice. */
  2906.       target_frame = Fselected_frame (Qnil);
  2907.     }
  2908.  
  2909.   /* Give the user the ability to completely reimplement this function in
  2910.      lisp via the `display-buffer-function'.
  2911.    */
  2912.   if (!NILP (Vdisplay_buffer_function))
  2913.     {
  2914.       struct gcpro gcpro1, gcpro2, gcpro3;
  2915.       GCPRO3 (buffer, not_this_window_p, override_frame);
  2916.       RETURN_UNGCPRO (call3 (Vdisplay_buffer_function,
  2917.                              buffer, not_this_window_p,
  2918.                  override_frame));
  2919.     }
  2920.  
  2921.   /* If the buffer has a dedicated frame, that takes precedence over the
  2922.      current frame, and over what the pre-display-buffer-function did.
  2923.    */
  2924.   if (!NILP (XBUFFER (buffer)->dedicated_frame) &&
  2925.       FRAME_LIVE_P (XFRAME (XBUFFER (buffer)->dedicated_frame))) /* XEmacs */
  2926.     target_frame = XBUFFER (buffer)->dedicated_frame;
  2927.  
  2928.   /* if override_frame is supplied, that takes precedence over everything.
  2929.      (This is gonna look bad if the pre-display-buffer-function raised
  2930.      some other frame already.)
  2931.    */
  2932.   if (!NILP (override_frame))
  2933.     target_frame = override_frame;
  2934.  
  2935.   CHECK_LIVE_FRAME (target_frame, 0);
  2936.  
  2937.   /* If we have switched frames, then set not_this_window_p to false.
  2938.      Switching frames means that selected_window is no longer the same
  2939.      as it was on entry -- it's the selected_window of target_frame
  2940.      instead of old_frame, so it's a fine candidate for display. */
  2941.   if (!EQ (old_frame, target_frame))
  2942.     not_this_window_p = Qnil;
  2943.  
  2944.   /* if it's in the selected window, and that's ok, then we're done. */
  2945.   if (NILP (not_this_window_p)
  2946.       && XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == XBUFFER (buffer))
  2947.     return Fselected_window (Qnil);
  2948.  
  2949.   /* Otherwise, find some window that it's already in, and return that,
  2950.      unless that window is the selected window and that isn't ok.
  2951.      What a contorted mess! */
  2952.   window = Fget_buffer_window (buffer, target_frame, Qnil);
  2953.   if (!NILP (window)
  2954.       && (NILP (not_this_window_p) || !EQ (window, Fselected_window (Qnil))))
  2955.     return window;
  2956.  
  2957. #if 0
  2958.   /* If there are no frames open that have more than a minibuffer,
  2959.      we need to create a new frame.  */
  2960.   if (pop_up_frames || last_nonminibuf_frame == 0)
  2961.     {
  2962.       window
  2963.     = Fframe_selected_window (call0 (Vpop_up_frame_function));
  2964.       Fset_window_buffer (window, buffer);
  2965. # if 0
  2966.       Fselect_frame (XWINDOW (window)->frame, Qnil);
  2967. # endif
  2968.       return window;
  2969.     }
  2970. #endif
  2971.  
  2972.   /* Otherwise, make it be in some window, splitting if appropriate/possible.
  2973.      Do not split a window if we are displaying the buffer in a different
  2974.      frame than that which was current when we were called.  (It is already
  2975.      in a different window by virtue of being in another frame.)
  2976.    */
  2977.   if ((pop_up_windows
  2978.        && EQ (target_frame, old_frame))
  2979.       || FRAME_MINIBUF_ONLY_P (selected_frame ()))
  2980.     {
  2981. #if 0
  2982.       if (FRAME_MINIBUF_ONLY_P (selected_frame ()))
  2983.     XSETFRAME (target_frame, last_nonminibuf_frame);
  2984. #endif
  2985.       /* Don't try to create a window if would get an error */
  2986.       if (split_height_threshold < window_min_height << 1)
  2987.     split_height_threshold = window_min_height << 1;
  2988.  
  2989.       /* Don't try to create a window if would get an error */
  2990.       if (split_width_threshold < window_min_width << 1)
  2991.     split_width_threshold = window_min_width << 1;
  2992.  
  2993.       window = Fget_largest_window (target_frame);
  2994.  
  2995.       if (!NILP (window)
  2996.       && window_char_height (XWINDOW (window), 1) >= split_height_threshold
  2997.       && (window_char_width (XWINDOW (window), 0) >= split_width_threshold
  2998.           ||
  2999.           (window_char_width (XWINDOW (window), 0)
  3000.            == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window)))))))
  3001.     window = Fsplit_window (window, Qnil, Qnil);
  3002.       else
  3003.     {
  3004.       window = Fget_lru_window (target_frame);
  3005.       if ((EQ (window, Fselected_window (Qnil))
  3006.            || EQ (XWINDOW (window)->parent, Qnil))
  3007.           && window_char_height (XWINDOW (window), 1)
  3008.           >= (window_min_height << 1))
  3009.         window = Fsplit_window (window, Qnil, Qnil);
  3010.     }
  3011.     }
  3012.   else
  3013.     window = Fget_lru_window (target_frame);
  3014.  
  3015.   /* Bring the window's previous buffer to the top of the MRU chain. */
  3016.   if (!NILP (XWINDOW (window)->buffer))
  3017.     record_buffer (XWINDOW (window)->buffer);
  3018.  
  3019.   Fset_window_buffer (window, buffer);
  3020.   return window;
  3021. }
  3022.  
  3023. void
  3024. temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
  3025. {
  3026.   /* This function can GC */
  3027.   Lisp_Object window;
  3028.   struct window *w;
  3029.   struct buffer *b = XBUFFER (buf);
  3030.  
  3031.   XBUFFER (buf)->save_modified = BUF_MODIFF (b);
  3032.   widen_buffer (b, 0);
  3033.   BUF_SET_PT (b, BUF_BEG (b));
  3034.  
  3035.   if (!EQ (Vtemp_buffer_show_function, Qnil))
  3036.     call1 (Vtemp_buffer_show_function, buf);
  3037.   else
  3038.     {
  3039.       window = Fdisplay_buffer (buf, Qnil, same_frame);
  3040.  
  3041.       if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
  3042.     Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
  3043.  
  3044.       Vminibuf_scroll_window = window;
  3045.       w = XWINDOW (window);
  3046.       w->hscroll = 0;
  3047.       set_marker_restricted (w->start[CURRENT_DISP], make_number (1), buf);
  3048.       set_marker_restricted (w->pointm[CURRENT_DISP], make_number (1), buf);
  3049.       set_marker_restricted (w->sb_point, make_number (1), buf);
  3050.     }
  3051. }
  3052.  
  3053. static void
  3054. make_dummy_parent (Lisp_Object window)
  3055. {
  3056.   Lisp_Object new = Qnil;
  3057.   struct window *o = XWINDOW (window);
  3058.   struct window *p = alloc_lcrecord (sizeof (struct window), 
  3059.                      lrecord_window);
  3060.   struct lcrecord_header preserve_me;
  3061.   int uid;
  3062.  
  3063.   XSETWINDOW (new, p);
  3064.   preserve_me = p->header;
  3065.   uid = p->header.uid;
  3066.   memcpy (p, o, sizeof (struct window));
  3067.   p->header = preserve_me;
  3068.   p->header.uid = uid;
  3069.  
  3070.   /* Don't copy the pointers to the line start cache or the face
  3071.      instances. */
  3072.   p->line_start_cache = Dynarr_new (struct line_start_cache);
  3073.   p->face_cache_elements = Dynarr_new (struct face_cache_element);
  3074.   p->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
  3075.  
  3076.   /* Put new into window structure in place of window */
  3077.   replace_window (window, new);
  3078.  
  3079.   o->next = Qnil;
  3080.   o->prev = Qnil;
  3081.   o->vchild = Qnil;
  3082.   o->hchild = Qnil;
  3083.   o->parent = new;
  3084.  
  3085.   p->start[CURRENT_DISP] = Qnil;
  3086.   p->start[DESIRED_DISP] = Qnil;
  3087.   p->start[CMOTION_DISP] = Qnil;
  3088.   p->pointm[CURRENT_DISP] = Qnil;
  3089.   p->pointm[DESIRED_DISP] = Qnil;
  3090.   p->pointm[CMOTION_DISP] = Qnil;
  3091.   p->sb_point = Qnil;
  3092.   p->buffer = Qnil;
  3093. }
  3094.  
  3095. DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
  3096.   "Split WINDOW, putting SIZE lines in the first of the pair.\n\
  3097. WINDOW defaults to selected one and SIZE to half its size.\n\
  3098. If optional third arg HOR-FLAG is non-nil, split side by side\n\
  3099. and put SIZE columns in the first of the pair.")
  3100.   (window, chsize, horflag)
  3101.      Lisp_Object window, chsize, horflag;
  3102. {
  3103.   Lisp_Object new;
  3104.   struct window *o, *p;
  3105.   struct frame *f;
  3106.   int size;
  3107.   int psize;
  3108.  
  3109.   if (NILP (window))
  3110.     window = Fselected_window (Qnil);
  3111.   else
  3112.     CHECK_WINDOW (window, 0);
  3113.  
  3114.   o = XWINDOW (window);
  3115.   f = XFRAME (WINDOW_FRAME (o));
  3116.  
  3117.   if (NILP (chsize))
  3118.     {
  3119.       if (!NILP (horflag))
  3120.     /* In the new scheme, we are symmetric with respect to separators
  3121.        so there is no need to do weird things here. */
  3122.     {
  3123.       psize = WINDOW_WIDTH (o) >> 1;
  3124.       size = window_pixel_width_to_char_width (o, psize, 0);
  3125.         }
  3126.       else
  3127.         {
  3128.       psize = WINDOW_HEIGHT (o) >> 1;
  3129.       size = window_pixel_height_to_char_height (o, psize, 1);
  3130.         }
  3131.     }
  3132.   else
  3133.     {
  3134.       CHECK_INT (chsize, 1);
  3135.       size = XINT (chsize);
  3136.       if (!NILP (horflag))
  3137.     psize = window_char_width_to_pixel_width (o, size, 0);
  3138.       else
  3139.     psize = window_char_height_to_pixel_height (o, size, 1);
  3140.     }
  3141.  
  3142.   if (MINI_WINDOW_P (o))
  3143.     error ("Attempt to split minibuffer window");
  3144.   else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
  3145.     error ("Attempt to split unsplittable frame");
  3146.  
  3147.   check_min_window_sizes ();
  3148.  
  3149.   if (NILP (horflag))
  3150.     {
  3151.       if (size < window_min_height
  3152.       || size + window_min_height > window_char_height (o, 1))
  3153. /*    args_out_of_range_3 (window, chsize, horflag); */
  3154.     error ("Window is not tall enough to split");
  3155.       if (NILP (o->parent)
  3156.       || NILP (XWINDOW (o->parent)->vchild))
  3157.     {
  3158.       make_dummy_parent (window);
  3159.       reset_face_cache_elements (XWINDOW (window));
  3160.       new = o->parent;
  3161.       XWINDOW (new)->vchild = window;
  3162.       XFRAME (o->frame)->mirror_dirty = 1;
  3163.     }
  3164.     }
  3165.   else
  3166.     {
  3167.       if (size < window_min_width
  3168.       || size + window_min_width > window_char_width (o, 0))
  3169. /*    args_out_of_range_3 (window, chsize, horflag); */
  3170.     error ("Window is not wide enough to split");
  3171.       if (NILP (o->parent)
  3172.       || NILP (XWINDOW (o->parent)->hchild))
  3173.     {
  3174.       make_dummy_parent (window);
  3175.       reset_face_cache_elements (XWINDOW (window));
  3176.       new = o->parent;
  3177.       XWINDOW (new)->hchild = window;
  3178.       XFRAME (o->frame)->mirror_dirty = 1;
  3179.     }
  3180.     }
  3181.  
  3182.   /* Now we know that window's parent is a vertical combination
  3183.      if we are dividing vertically, or a horizontal combination
  3184.      if we are making side-by-side windows */
  3185.  
  3186.   MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
  3187.   new = allocate_window ();
  3188.   p = XWINDOW (new);
  3189.  
  3190.   p->frame = o->frame;
  3191.   p->next = o->next;
  3192.   if (!NILP (p->next))
  3193.     XWINDOW (p->next)->prev = new;
  3194.   p->prev = window;
  3195.   o->next = new;
  3196.   p->parent = o->parent;
  3197.   p->buffer = Qt;
  3198.  
  3199.   reset_face_cache_elements (p);
  3200.   reset_glyph_cache_elements (p);
  3201.   Fset_window_buffer (new, o->buffer);
  3202.   
  3203.  
  3204.   /* Apportion the available frame space among the two new windows */
  3205.  
  3206.   if (!NILP (horflag))
  3207.     {
  3208.       WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
  3209.       WINDOW_TOP (p) = WINDOW_TOP (o);
  3210.       WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
  3211.       WINDOW_WIDTH (o) = psize;
  3212.       WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
  3213.     }
  3214.   else
  3215.     {
  3216.       WINDOW_LEFT (p) = WINDOW_LEFT (o);
  3217.       WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
  3218.       WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
  3219.       WINDOW_HEIGHT (o) = psize;
  3220.       WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
  3221.     }
  3222.  
  3223.   XFRAME (p->frame)->mirror_dirty = 1;
  3224.   return new;
  3225. }
  3226.  
  3227. static void change_window_height (int delta, int widthflag);
  3228.  
  3229. DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "_p",
  3230.   "Make current window ARG lines bigger.\n\
  3231. From program, optional second arg non-nil means grow sideways ARG columns.")
  3232.   (n, side)
  3233.      Lisp_Object n, side;
  3234. {
  3235.   CHECK_INT (n, 0);
  3236.   change_window_height (XINT (n), !NILP (side));
  3237.   return Qnil;
  3238. }
  3239.  
  3240. DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "_p",
  3241.   "Make current window ARG lines smaller.\n\
  3242. From program, optional second arg non-nil means shrink sideways ARG columns.")
  3243.   (n, side)
  3244.      Lisp_Object n, side;
  3245. {
  3246.   CHECK_INT (n, 0);
  3247.   change_window_height (-XINT (n), !NILP (side));
  3248.   return Qnil;
  3249. }
  3250.  
  3251. static int
  3252. window_pixel_height (Lisp_Object window)
  3253. {
  3254.   struct window *w = XWINDOW (window);
  3255.   return WINDOW_HEIGHT (w);
  3256. }
  3257.  
  3258. static int
  3259. window_pixel_height_to_char_height (struct window *w, int pixel_height,
  3260.                     int include_modeline_p)
  3261. {
  3262.   int avail_height;
  3263.   int defheight, defwidth;
  3264.   int char_height;
  3265.   Lisp_Object window;
  3266.   
  3267.   XSETWINDOW (window, w);
  3268.   
  3269.   avail_height = (pixel_height -
  3270.           window_top_gutter_height (w) -
  3271.           window_bottom_gutter_height (w) +
  3272.           (include_modeline_p ? window_modeline_height (w) : 0));
  3273.   
  3274.   default_face_height_and_width (window, &defheight, &defwidth);
  3275.  
  3276.   char_height = avail_height / defheight;
  3277.  
  3278.   /* It's the calling function's responsibility to check these values
  3279.      and make sure they're not out of range.
  3280.  
  3281.      #### We need to go through the calling functions and actually
  3282.      do this. */
  3283.   if (char_height < 0)
  3284.     return 0;
  3285.   else
  3286.     return char_height;
  3287. }
  3288.  
  3289. static int
  3290. window_char_height_to_pixel_height (struct window *w, int char_height,
  3291.                     int include_modeline_p)
  3292. {
  3293.   int avail_height;
  3294.   int defheight, defwidth;
  3295.   int pixel_height;
  3296.  
  3297.   Lisp_Object window;
  3298.   
  3299.   XSETWINDOW (window, w);
  3300.   
  3301.   default_face_height_and_width (window, &defheight, &defwidth);
  3302.  
  3303.   avail_height = char_height * defheight;
  3304.   pixel_height = (avail_height + 
  3305.           window_top_gutter_height (w) +
  3306.           window_bottom_gutter_height (w) -
  3307.           (include_modeline_p ? window_modeline_height (w) : 0));
  3308.   
  3309.  
  3310.   /* It's the calling function's responsibility to check these values
  3311.      and make sure they're not out of range.
  3312.  
  3313.      #### We need to go through the calling functions and actually
  3314.      do this. */
  3315.   if (pixel_height < 0)
  3316.     return 0;
  3317.   else
  3318.     return pixel_height;
  3319. }
  3320.  
  3321. /* Return number of default lines of text can fit in space not taken
  3322.    up by modeline and horizontal scrollbar (if INCLUDE_MODELINE_P is
  3323.    non-zero, however, include the modeline in the space considered).
  3324.    */
  3325. int
  3326. window_char_height (struct window *w, int include_modeline_p)
  3327. {
  3328.   return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
  3329.                          include_modeline_p);
  3330. }
  3331.  
  3332. /*
  3333.  * Return number of lines currently displayed in window w.  If
  3334.  * end-of-buffer is displayed then the area below end-of-buffer is assume
  3335.  * to be blank lines of default height.
  3336.  * Does not include the modeline.
  3337.  */
  3338. int
  3339. window_displayed_height (struct window *w)
  3340. {
  3341.   struct buffer *b = XBUFFER (w->buffer);
  3342.   display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
  3343.   int num_lines;
  3344.   Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
  3345.                ? -1
  3346.                : w->window_end_pos[CURRENT_DISP]);
  3347.  
  3348.   if (!Dynarr_length (dla))
  3349.     return window_char_height (w, 0);
  3350.  
  3351.   num_lines = Dynarr_length (dla);
  3352.  
  3353.   /* #### Document and assert somewhere that w->window_end_pos == -1
  3354.      indicates that end-of-buffer is being displayed. */
  3355.   if (end_pos == -1)
  3356.     {
  3357.       struct display_line *dl = Dynarr_atp (dla, 0);
  3358.       int ypos1 = dl->ypos + dl->descent;
  3359.       int ypos2 = WINDOW_TEXT_BOTTOM (w);
  3360.       Lisp_Object window;
  3361.       int defheight, defwidth;
  3362.  
  3363.       XSETWINDOW (window, w);
  3364.  
  3365.       if (dl->modeline)
  3366.     {
  3367.       num_lines--;
  3368.  
  3369.       if (Dynarr_length (dla) == 1)
  3370.         ypos1 = WINDOW_TEXT_TOP (w);
  3371.       else
  3372.         {
  3373.           dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
  3374.           /* If this line is clipped then we know that there is no
  3375.                  blank room between eob and the modeline.  If we are
  3376.                  scrolling on clipped lines just know off the clipped
  3377.                  line and return .*/
  3378.           if (scroll_on_clipped_lines && dl->clip)
  3379.         return (num_lines - 1);
  3380.           ypos1 = dl->ypos + dl->descent - dl->clip;
  3381.         }
  3382.     }
  3383.  
  3384.       default_face_height_and_width (window, &defheight, &defwidth);
  3385.       /* #### This probably needs to know about the clipping area once a
  3386.          final definition is decided on. */
  3387.       num_lines += ((ypos2 - ypos1) / defheight);
  3388.     }
  3389.   else
  3390.     {
  3391.       if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
  3392.     num_lines--;
  3393.  
  3394.       if (scroll_on_clipped_lines
  3395.       && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
  3396.     num_lines--;
  3397.     }
  3398.  
  3399.   return num_lines;
  3400. }
  3401.  
  3402. static int
  3403. window_pixel_width (Lisp_Object window)
  3404. {
  3405.   struct window *w = XWINDOW (window);
  3406.   return WINDOW_WIDTH (w);
  3407. }
  3408.  
  3409. static int
  3410. window_pixel_width_to_char_width (struct window *w, int pixel_width,
  3411.                   int include_margins_p)
  3412. {
  3413.   int avail_width;
  3414.   int char_width;
  3415.   int defheight, defwidth;
  3416.   Lisp_Object window;
  3417.   
  3418.   XSETWINDOW (window, w);
  3419.   
  3420.   avail_width = (pixel_width -
  3421.          window_left_gutter_width (w, 0) -
  3422.          window_right_gutter_width (w, 0) -
  3423.          (include_margins_p ? 0 : window_left_margin_width (w)) -
  3424.          (include_margins_p ? 0 : window_right_margin_width (w)));
  3425.   
  3426.   default_face_height_and_width (window, &defheight, &defwidth);
  3427.   
  3428.   char_width = (avail_width / defwidth);
  3429.  
  3430.   /* It's the calling function's responsibility to check these values
  3431.      and make sure they're not out of range.
  3432.  
  3433.      #### We need to go through the calling functions and actually
  3434.      do this. */
  3435.   if (char_width < 0)
  3436.     return 0;
  3437.   else
  3438.     return char_width;
  3439. }
  3440.  
  3441. static int
  3442. window_char_width_to_pixel_width (struct window *w, int char_width,
  3443.                   int include_margins_p)
  3444. {
  3445.   int avail_width;
  3446.   int pixel_width;
  3447.   int defheight, defwidth;
  3448.   Lisp_Object window;
  3449.  
  3450.   XSETWINDOW (window, w);
  3451.  
  3452.   default_face_height_and_width (window, &defheight, &defwidth);
  3453.  
  3454.   avail_width = char_width * defwidth;
  3455.   pixel_width = (avail_width +
  3456.          window_left_gutter_width (w, 0) +
  3457.          window_right_gutter_width (w, 0) +
  3458.          (include_margins_p ? 0 : window_left_margin_width (w)) +
  3459.          (include_margins_p ? 0 : window_right_margin_width (w)));
  3460.  
  3461.   /* It's the calling function's responsibility to check these values
  3462.      and make sure they're not out of range.
  3463.  
  3464.      #### We need to go through the calling functions and actually
  3465.      do this. */
  3466.   if (pixel_width < 0)
  3467.     return 0;
  3468.   else
  3469.     return pixel_width;
  3470. }
  3471.  
  3472. /* This returns the usable space which doesn't include space needed by
  3473.    scrollbars or divider lines. */
  3474. int
  3475. window_char_width (struct window *w, int include_margins_p)
  3476. {
  3477.   return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
  3478.                        include_margins_p);
  3479. }
  3480.  
  3481. #define MINSIZE(w)                        \
  3482.   (widthflag                            \
  3483.    ? window_min_width * defwidth                \
  3484.    : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
  3485.  
  3486. #define CURBEG(w) \
  3487.   *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
  3488.  
  3489. #define CURSIZE(w) \
  3490.   *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
  3491.  
  3492. #define CURCHARSIZE(w) \
  3493.   (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
  3494.  
  3495. #define MINCHARSIZE(window) \
  3496.   (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
  3497.    ? 1 : window_min_height)
  3498.  
  3499. /* Unlike set_window_pixheight, this function
  3500.    also changes the heights of the siblings so as to
  3501.    keep everything consistent. */
  3502.  
  3503. static void
  3504. change_window_height (int delta, int widthflag)
  3505. {
  3506.   Lisp_Object parent;
  3507.   Lisp_Object window;
  3508.   struct window *w;
  3509.   struct frame *f;
  3510.   int *sizep;
  3511.   int (*sizefun) (Lisp_Object) = (widthflag
  3512.                   ? window_pixel_width
  3513.                   : window_pixel_height);
  3514.   void (*setsizefun) (Lisp_Object, int, int) = (widthflag
  3515.                         ? set_window_pixwidth
  3516.                         : set_window_pixheight);
  3517.   int dim;
  3518.   int defheight, defwidth;
  3519.  
  3520.   if (delta == 0)
  3521.     return;
  3522.  
  3523.   check_min_window_sizes ();
  3524.  
  3525.   if (EQ (Fselected_window (Qnil),
  3526.       FRAME_ROOT_WINDOW
  3527.       (XFRAME (XWINDOW (Fselected_window (Qnil))->frame))))
  3528.     error ("Won't change only window");
  3529.  
  3530.   f = selected_frame ();
  3531.   window = Fselected_window (Qnil);
  3532.  
  3533.   /* #### This is very likely incorrect and instead the char_to_pixel_
  3534.      functions should be called. */
  3535.   default_face_height_and_width (window, &defheight, &defwidth);
  3536.  
  3537.   while (1)
  3538.     {
  3539.       w = XWINDOW (window);
  3540.       parent = w->parent;
  3541.       if (NILP (parent))
  3542.     {
  3543.       if (widthflag)
  3544.         error ("No other window to side of this one");
  3545.       break;
  3546.     }
  3547.       if (widthflag
  3548.           ? !NILP (XWINDOW (parent)->hchild)
  3549.       : !NILP (XWINDOW (parent)->vchild))
  3550.     break;
  3551.       window = parent;
  3552.     }
  3553.  
  3554.   sizep = &CURSIZE (w);
  3555.   dim = CURCHARSIZE (w);
  3556.  
  3557.   if ((dim + delta) < MINCHARSIZE (window))
  3558.     {
  3559.       if (MINI_WINDOW_P (XWINDOW (window)))
  3560.     return;
  3561.       else if (!NILP (parent))
  3562.     {
  3563.       Fdelete_window (window);
  3564.       return;
  3565.     }
  3566.     }
  3567.  
  3568.   delta *= (widthflag ? defwidth : defheight);
  3569.  
  3570.   {
  3571.     int maxdelta;
  3572.  
  3573.     maxdelta = ((!NILP (parent))
  3574.                 ? (*sizefun) (parent) - *sizep
  3575.         : ((!NILP (w->next))
  3576.                    ? (*sizefun) (w->next) - MINSIZE (w->next)
  3577.                    : ((!NILP (w->prev))
  3578.                       ? (*sizefun) (w->prev) - MINSIZE (w->prev)
  3579.                       /* This is a frame with only one window, 
  3580.                          a minibuffer-only or a minibufferless frame.  */
  3581.                       : (delta = 0))));
  3582.  
  3583.     if (delta > maxdelta)
  3584.       /* This case traps trying to make the minibuffer
  3585.      the full frame, or make the only window aside from the
  3586.      minibuffer the full frame.  */
  3587.       delta = maxdelta;
  3588.  
  3589.     if (delta == 0)
  3590.       return;
  3591.  
  3592. #if 0 /* FSFmacs */
  3593.     /* #### Chuck: is this correct? */
  3594.     if (*sizep + delta < MINSIZE (window))
  3595.       {
  3596.     Fdelete_window (window);
  3597.     return;
  3598.       }
  3599. #endif
  3600.   }
  3601.  
  3602.   if (!NILP (w->next) &&
  3603.       (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
  3604.     {
  3605.       CURBEG (XWINDOW (w->next)) += delta;
  3606.       (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
  3607.       (*setsizefun) (window, *sizep + delta, 0);
  3608.     }
  3609.   else if (!NILP (w->prev) &&
  3610.        (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
  3611.     {
  3612.       (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
  3613.       CURBEG (w) -= delta;
  3614.       (*setsizefun) (window, *sizep + delta, 0);
  3615.     }
  3616.   else
  3617.     {
  3618.       int delta1;
  3619.       int opht = (*sizefun) (parent);
  3620.  
  3621.       /* If trying to grow this window to or beyond size of the parent,
  3622.      make delta1 so big that, on shrinking back down,
  3623.      all the siblings end up with less than one line and are deleted.  */
  3624.       if (opht <= *sizep + delta)
  3625.     delta1 = opht * opht * 2;
  3626.       /* Otherwise, make delta1 just right so that if we add delta1
  3627.      lines to this window and to the parent, and then shrink
  3628.      the parent back to its original size, the new proportional
  3629.      size of this window will increase by delta.  */
  3630.       else
  3631.     delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
  3632.  
  3633.       /* Add delta1 lines or columns to this window, and to the parent,
  3634.      keeping things consistent while not affecting siblings.  */
  3635.       CURSIZE (XWINDOW (parent)) = opht + delta1;
  3636.       (*setsizefun) (window, *sizep + delta1, 0);
  3637.  
  3638.       /* Squeeze out delta1 lines or columns from our parent,
  3639.      shriking this window and siblings proportionately.
  3640.      This brings parent back to correct size.
  3641.      Delta1 was calculated so this makes this window the desired size,
  3642.      taking it all out of the siblings.  */
  3643.       (*setsizefun) (parent, opht, 0);
  3644.     }
  3645.  
  3646.   SET_LAST_MODIFIED (w, 0);
  3647.   SET_LAST_FACECHANGE (w);
  3648.   MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
  3649. }
  3650. #undef MINSIZE
  3651. #undef CURBEG
  3652. #undef CURSIZE
  3653. #undef CURCHARSIZE
  3654. #undef MINCHARSIZE
  3655.  
  3656.  
  3657.  
  3658. /* Scroll contents of window WINDOW up N lines.  */
  3659. void
  3660. window_scroll (Lisp_Object window, Lisp_Object n, int direction, int no_error)
  3661. {
  3662.   struct window *w = XWINDOW (window);
  3663.   struct buffer *b = XBUFFER (w->buffer);
  3664.   int selected = EQ (window, Fselected_window (Qnil));
  3665.   int value = 0;
  3666.   Bufpos opoint;
  3667.   Lisp_Object point, tem;
  3668.  
  3669.   if (selected)
  3670.     point = make_number (BUF_PT (b));
  3671.   else
  3672.     {
  3673.       Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
  3674.  
  3675.       if (pos < BUF_BEGV (b))
  3676.     pos = BUF_BEGV (b);
  3677.       else if (pos > BUF_ZV (b))
  3678.     pos = BUF_ZV (b);
  3679.  
  3680.       point = make_number (pos);
  3681.     }
  3682.  
  3683.   /* #### When the fuck does this happen?  I'm so glad that history has
  3684.      completely documented the behavior of the scrolling functions under
  3685.      all circumstances. */
  3686.   tem = Fpos_visible_in_window_p (point, window);
  3687.   if (NILP (tem))
  3688.     {
  3689.       Fvertical_motion (make_number (-window_char_height (w, 0) / 2), window);
  3690.       Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
  3691.       w->force_start = 1;
  3692.       opoint = BUF_PT (b);
  3693.       BUF_SET_PT (b, XINT (point));
  3694.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  3695.       BUF_SET_PT (b, opoint);
  3696.       MARK_WINDOWS_CHANGED (w);
  3697.     }
  3698.  
  3699.   if (!NILP (n))
  3700.     {
  3701.       if (EQ (n, Qminus))
  3702.     direction *= -1;
  3703.       else
  3704.     {
  3705.       n = Fprefix_numeric_value (n);
  3706.       value = XINT (n) * direction;
  3707.  
  3708.       if (!value)
  3709.         return;    /* someone just made a pointless call */
  3710.     }
  3711.     }
  3712.  
  3713.   /* If the user didn't specify how far to scroll then we have to figure it
  3714.      out by ourselves. */
  3715.   if (NILP (n) || EQ (n, Qminus))
  3716.     {
  3717.       /* Going forwards is easy.  If that is what we are doing then just
  3718.      set value and the section which handles the user specifying a
  3719.      positive value will work. */
  3720.       if (direction == 1)
  3721.     {
  3722.       value = window_displayed_height (w) - next_screen_context_lines;
  3723.       value = (value < 1 ? 1 : value);
  3724.     }
  3725.  
  3726.       /* Going backwards is hard.  We can't use the same loop used if the
  3727.          user specified a negative value because we care about
  3728.          next_screen_context_lines.  In a variable height world you don't
  3729.          know how many lines above you can actually be displayed and still
  3730.          have the context lines appear.  So we leave value set to 0 and add
  3731.          a separate section to deal with this. */
  3732.  
  3733.     }
  3734.  
  3735.   if (direction == 1 && !value)
  3736.     {
  3737.       return;
  3738.     }
  3739.   else if (value > 0)
  3740.     {
  3741.       int vtarget;
  3742.       Bufpos startp, old_start;
  3743.  
  3744.       old_start = marker_position (w->start[CURRENT_DISP]);
  3745.       startp = vmotion (w, old_start, value, &vtarget);
  3746.  
  3747.       if (vtarget < value &&
  3748.       (w->window_end_pos[CURRENT_DISP] == -1
  3749.        || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
  3750.     {
  3751.       if (no_error)
  3752.         return;
  3753.       else
  3754.         signal_error (Qend_of_buffer, Qnil);
  3755.     }
  3756.       else
  3757.     {
  3758.       set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
  3759.                  w->buffer);
  3760.       w->force_start = 1;
  3761.       opoint = BUF_PT (b);
  3762.       BUF_SET_PT (b, startp);
  3763.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  3764.       BUF_SET_PT (b, opoint);
  3765.       MARK_WINDOWS_CHANGED (w);
  3766.  
  3767.       if (!point_would_be_visible (w, startp, XINT (point)))
  3768.         {
  3769.           if (selected)
  3770.         BUF_SET_PT (b, startp);
  3771.           else
  3772.         set_marker_restricted (w->pointm[CURRENT_DISP],
  3773.                        make_number (startp),
  3774.                        w->buffer);
  3775.         }
  3776.     }
  3777.     }
  3778.   else if (value < 0)
  3779.     {
  3780.       int vtarget;
  3781.       Bufpos startp, old_start;
  3782.  
  3783.       old_start = marker_position (w->start[CURRENT_DISP]);
  3784.       startp = vmotion (w, old_start, value, &vtarget);
  3785.  
  3786.       if (vtarget > value
  3787.       && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
  3788.     {
  3789.       if (no_error)
  3790.         return;
  3791.       else
  3792.         signal_error (Qbeginning_of_buffer, Qnil);
  3793.     }
  3794.       else
  3795.     {
  3796.       set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
  3797.                  w->buffer);
  3798.       w->force_start = 1;
  3799.       opoint = BUF_PT (b);
  3800.       BUF_SET_PT (b, startp);
  3801.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  3802.       BUF_SET_PT (b, opoint);
  3803.       MARK_WINDOWS_CHANGED (w);
  3804.  
  3805.       if (!point_would_be_visible (w, startp, XINT (point)))
  3806.         {
  3807.           Bufpos new_point;
  3808.  
  3809.           if (MINI_WINDOW_P (w))
  3810.         new_point = startp;
  3811.           else
  3812.         new_point = start_of_last_line (w, startp);
  3813.  
  3814.           if (selected)
  3815.         BUF_SET_PT (b, new_point);
  3816.           else
  3817.         set_marker_restricted (w->pointm[CURRENT_DISP],
  3818.                        make_number (new_point),
  3819.                        w->buffer);
  3820.         }
  3821.     }
  3822.     }
  3823.   else    /* value == 0 && direction == -1 */
  3824.     {
  3825.       if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
  3826.     {
  3827.       if (no_error)
  3828.         return;
  3829.       else
  3830.         signal_error (Qbeginning_of_buffer, Qnil);
  3831.     }
  3832.       else
  3833.     {
  3834.       int vtarget;
  3835.       int movement = next_screen_context_lines - 1;
  3836.       Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
  3837.       Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
  3838.       Bufpos startp =
  3839.         start_with_point_on_display_line (w, bottom,
  3840.                           -1 - (movement - vtarget));
  3841.  
  3842.       if (startp >= old_startp)
  3843.         startp = vmotion (w, old_startp, -1, NULL);
  3844.  
  3845.       set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
  3846.                  w->buffer);
  3847.       w->force_start = 1;
  3848.       opoint = BUF_PT (b);
  3849.       BUF_SET_PT (b, startp);
  3850.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  3851.       BUF_SET_PT (b, opoint);
  3852.       MARK_WINDOWS_CHANGED (w);
  3853.  
  3854.       if (!point_would_be_visible (w, startp, XINT (point)))
  3855.         {
  3856.           Bufpos new_point = start_of_last_line (w, startp);
  3857.  
  3858.           if (selected)
  3859.         BUF_SET_PT (b, new_point);
  3860.           else
  3861.         set_marker_restricted (w->pointm[CURRENT_DISP],
  3862.                        make_number (new_point),
  3863.                        w->buffer);
  3864.         }
  3865.     }
  3866.     }
  3867.  
  3868. }
  3869.  
  3870. DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "_P",
  3871.   "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
  3872. A near full screen is `next-screen-context-lines' less than a full screen.\n\
  3873. Negative ARG means scroll downward.\n\
  3874. When calling from a program, supply a number as argument or nil.")
  3875.   (n)
  3876.      Lisp_Object n;
  3877. {
  3878.   window_scroll (Fselected_window (Qnil), n, 1, 0);
  3879.   return Qnil;
  3880. }
  3881.  
  3882. DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "_P",
  3883.   "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
  3884. A near full screen is `next-screen-context-lines' less than a full screen.\n\
  3885. Negative ARG means scroll upward.\n\
  3886. When calling from a program, supply a number as argument or nil.")
  3887.   (n)
  3888.      Lisp_Object n;
  3889. {
  3890.   window_scroll (Fselected_window (Qnil), n, -1, 0);
  3891.   return Qnil;
  3892. }
  3893.  
  3894. DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
  3895.   "Return the other window for \"other window scroll\" commands.\n\
  3896. If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
  3897. specifies the window.\n\
  3898. If `other-window-scroll-buffer' is non-nil, a window\n\
  3899. showing that buffer is used.")
  3900.   ()
  3901. {
  3902.   Lisp_Object window;
  3903.   Lisp_Object selected_window = Fselected_window (Qnil);
  3904.  
  3905.   if (MINI_WINDOW_P (XWINDOW (selected_window ))
  3906.       && !NILP (Vminibuf_scroll_window))
  3907.     window = Vminibuf_scroll_window;
  3908.   /* If buffer is specified, scroll that buffer.  */
  3909.   else if (!NILP (Vother_window_scroll_buffer))
  3910.     {
  3911.       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
  3912.       if (NILP (window))
  3913.     window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
  3914.     }
  3915.   else
  3916.     {
  3917.       /* Nothing specified; look for a neighboring window on the same
  3918.      frame.  */
  3919.       window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
  3920.  
  3921.       if (EQ (window, selected_window))
  3922.     /* That didn't get us anywhere; look for a window on another
  3923.            visible frame.  */
  3924.     do
  3925.       window = Fnext_window (window, Qnil, Qt, Qnil);
  3926.     while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
  3927.            && ! EQ (window, selected_window));
  3928.     }
  3929.  
  3930.   CHECK_LIVE_WINDOW (window, 0);
  3931.  
  3932.   if (EQ (window, selected_window))
  3933.     error ("There is no other window");
  3934.  
  3935.   return window;
  3936.  }
  3937.  
  3938. DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "_P",
  3939.   "Scroll next window upward ARG lines; or near full frame if no ARG.\n\
  3940. The next window is the one below the current one; or the one at the top\n\
  3941. if the current one is at the bottom.  Negative ARG means scroll downward.\n\
  3942. When calling from a program, supply a number as argument or nil.\n\
  3943. \n\
  3944. If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
  3945. specifies the window to scroll.\n\
  3946. If `other-window-scroll-buffer' is non-nil, scroll the window\n\
  3947. showing that buffer, popping the buffer up if necessary.")
  3948.   (n)
  3949.      Lisp_Object n;
  3950. {
  3951.   window_scroll (Fother_window_for_scrolling (), n, 1, 0);
  3952.   return Qnil;
  3953. }
  3954.  
  3955. DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "_P",
  3956.   "Scroll selected window display ARG columns left.\n\
  3957. Default for ARG is window width minus 2.")
  3958.   (arg)
  3959.      Lisp_Object arg;
  3960. {
  3961.   Lisp_Object window = Fselected_window (Qnil);
  3962.   struct window *w = XWINDOW (window);
  3963.  
  3964.   if (NILP (arg))
  3965.     arg = make_number (window_char_width (w, 0) - 2);
  3966.   else
  3967.     arg = Fprefix_numeric_value (arg);
  3968.  
  3969.   return
  3970.     Fset_window_hscroll (window, make_number (w->hscroll + XINT (arg)));
  3971. }
  3972.  
  3973. DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "_P",
  3974.   "Scroll selected window display ARG columns right.\n\
  3975. Default for ARG is window width minus 2.")
  3976.   (arg)
  3977.      Lisp_Object arg;
  3978. {
  3979.   Lisp_Object window = Fselected_window (Qnil);
  3980.   struct window *w = XWINDOW (window);
  3981.  
  3982.   if (NILP (arg))
  3983.     arg = make_number (window_char_width (w, 0) - 2);
  3984.   else
  3985.     arg = Fprefix_numeric_value (arg);
  3986.  
  3987.   return
  3988.     Fset_window_hscroll (window, make_number (w->hscroll - XINT (arg)));
  3989. }
  3990.  
  3991. DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "_P",
  3992.   "Center point in WINDOW and redisplay frame.  With ARG, put point on line ARG.\n\
  3993. The desired position of point is always relative to the window.\n\
  3994. Just C-u as prefix means put point in the center of the window.\n\
  3995. No arg (i.e., it is nil) erases the entire frame and then\n\
  3996. redraws with point in the center of the window.\n\
  3997. If WINDOW is nil, the selected window is used.")
  3998.   (n, window)
  3999.      Lisp_Object n, window;
  4000. {
  4001.   struct window *w;
  4002.   struct buffer *b;
  4003.   Bufpos startp;
  4004.   Bufpos opoint;
  4005.  
  4006.   if (NILP (window))
  4007.     window = Fselected_window (Qnil);
  4008.   else
  4009.     CHECK_WINDOW (window, 0);
  4010.   w = XWINDOW (window);
  4011.   b = XBUFFER (w->buffer);
  4012.  
  4013.   opoint = BUF_PT (b);
  4014.  
  4015.   if (NILP (n) || CONSP (n))
  4016.     {
  4017.       struct frame *f = XFRAME (w->frame);
  4018.  
  4019.       if (NILP (n))
  4020.     {
  4021.       MARK_FRAME_CHANGED (f);
  4022.       SET_FRAME_CLEAR (f);
  4023.     }
  4024.  
  4025.       startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
  4026.     }
  4027.   else
  4028.     {
  4029.       n = Fprefix_numeric_value (n);
  4030.       CHECK_INT (n, 0);
  4031.  
  4032.       startp = start_with_point_on_display_line (w, opoint, XINT (n));
  4033.     }
  4034.  
  4035.   Fset_marker (w->start[CURRENT_DISP], make_number (startp), w->buffer);
  4036.   /* Is start_at_line_beg still needed?  Do we still need to
  4037.      contort to set it? */
  4038.   BUF_SET_PT (b, startp);
  4039.   w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  4040.   BUF_SET_PT (b, opoint);
  4041.  
  4042.   w->force_start = 1;
  4043.   MARK_WINDOWS_CHANGED (w);
  4044.   return Qnil;
  4045. }
  4046.  
  4047. DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
  4048.   1, 2, "_P",
  4049.   "Position point relative to WINDOW.\n\
  4050. With no argument, position text at center of window.\n\
  4051. An argument specifies window line; zero means top of window,\n\
  4052. negative means relative to bottom of window.\n\
  4053. If WINDOW is nil, the selected window is used.")
  4054.   (arg, window)
  4055.      Lisp_Object arg, window;
  4056. {
  4057.   struct window *w;
  4058.   struct buffer *b;
  4059.   int height;
  4060.   Bufpos start, new_point;
  4061.   int selected;
  4062.  
  4063.   if (NILP (window))
  4064.     window = Fselected_window (Qnil);
  4065.   else
  4066.     CHECK_WINDOW (window, 0);
  4067.   w = XWINDOW (window);
  4068.   b = XBUFFER (w->buffer);
  4069.  
  4070.   height = window_displayed_height (w);
  4071.   selected = EQ (window, Fselected_window (XFRAME (w->frame)->device));
  4072.  
  4073.   if (NILP (arg))
  4074.     {
  4075.       int retval;
  4076.  
  4077.       if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
  4078.       && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
  4079.     {
  4080.       new_point = point_at_center (w, CURRENT_DISP, 0, 0, 0);
  4081.  
  4082.       if (selected)
  4083.         BUF_SET_PT (b, new_point);
  4084.       else
  4085.         Fset_window_point (window, make_number (new_point));
  4086.  
  4087.       retval = line_at_center (w, CURRENT_DISP);
  4088.     }
  4089.       else
  4090.     {
  4091.       start = marker_position (w->start[CURRENT_DISP]);
  4092.       if (start < BUF_BEGV (b))
  4093.         start = BUF_BEGV (b);
  4094.       else if (start > BUF_ZV (b))
  4095.         start = BUF_ZV (b);
  4096.  
  4097.       if (selected)
  4098.         new_point = BUF_PT (b);
  4099.       else
  4100.         new_point = marker_position (w->pointm[CURRENT_DISP]);
  4101.  
  4102.       new_point = point_at_center (w, CMOTION_DISP, 1, start, BUF_PT (b));
  4103.  
  4104.       if (selected)
  4105.         BUF_SET_PT (b, new_point);
  4106.       else
  4107.         Fset_window_point (window, make_number (new_point));
  4108.  
  4109.       retval = line_at_center (w, CMOTION_DISP);
  4110.     }
  4111.  
  4112.       return (make_number (retval));
  4113.     }
  4114.   else
  4115.     {
  4116.       /* #### Is this going to work right when at eob? */
  4117.       arg = Fprefix_numeric_value (arg);
  4118.       if (XINT (arg) < 0)
  4119.     XSETINT (arg, XINT (arg) + height);
  4120.     }
  4121.  
  4122.   start = marker_position (w->start[CURRENT_DISP]);
  4123.   if (start < BUF_BEGV (b) || start > BUF_ZV (b))
  4124.     {
  4125.       if (selected)
  4126.     new_point = BUF_PT (b);
  4127.       else
  4128.     new_point = marker_position (w->pointm[CURRENT_DISP]);
  4129.  
  4130.       new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
  4131.  
  4132.       if (selected)
  4133.     BUF_SET_PT (b, new_point);
  4134.       else
  4135.     Fset_window_point (window, make_number (new_point));
  4136.  
  4137.       Fset_marker (w->start[CURRENT_DISP], make_number (new_point),
  4138.            w->buffer);
  4139.       /* #### This isn't going to give the correct result if the
  4140.          window being worked with is not selected. */
  4141.       w->start_at_line_beg = !NILP (Fbolp (w->buffer));
  4142.       w->force_start = 1;
  4143.     }
  4144.   else
  4145.     {
  4146.       if (selected)
  4147.     BUF_SET_PT (b, start);
  4148.       else
  4149.     Fset_window_point (window, make_number (start));
  4150.     }
  4151.  
  4152.   if (selected)
  4153.     return Fvertical_motion (arg, window);
  4154.   else
  4155.     {
  4156.       int vpos;
  4157.       new_point = vmotion (XWINDOW (window),
  4158.                marker_position (w->pointm[CURRENT_DISP]),
  4159.                XINT (arg), &vpos);
  4160.       Fset_window_point (window, make_number (new_point));
  4161.       return make_number (vpos);
  4162.     }
  4163. }
  4164.  
  4165.  
  4166. static int
  4167. map_windows_1 (Lisp_Object window,
  4168.            int (*mapfun) (struct window *w, void *closure),
  4169.            void *closure)
  4170. {
  4171.   int retval; 
  4172.  
  4173.   for (; !NILP (window); window = XWINDOW (window)->next)
  4174.     {
  4175.       struct window *w = XWINDOW (window);
  4176.       if (!NILP (w->vchild))
  4177.     retval = map_windows_1 (w->vchild, mapfun, closure);
  4178.       else if (!NILP (w->hchild))
  4179.     retval = map_windows_1 (w->hchild, mapfun, closure);
  4180.       else
  4181.     retval = (mapfun) (w, closure);
  4182.       if (retval)
  4183.     return retval;
  4184.     }
  4185.  
  4186.   return 0;
  4187. }
  4188.  
  4189. /* Map MAPFUN over the windows in F.  CLOSURE is passed to each
  4190.    invocation of MAPFUN.  If any invocation of MAPFUN returns non-zero,
  4191.    the mapping is halted and the value returned is the return value
  4192.    of map_windows().  Otherwise, map_windows() maps over all windows
  4193.    in F and returns 0. */
  4194.  
  4195. int
  4196. map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
  4197.          void *closure)
  4198. {
  4199.   return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
  4200. }
  4201.  
  4202.  
  4203. static void
  4204. modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
  4205.                    Lisp_Object oldval)
  4206. {
  4207.   w->shadow_thickness_changed = 1;
  4208.   MARK_WINDOWS_CHANGED (w);
  4209. }
  4210.  
  4211. /* also used in scrollbar.c */
  4212. void
  4213. some_window_value_changed (Lisp_Object specifier, struct window *w,
  4214.                Lisp_Object oldval)
  4215. {
  4216.   MARK_WINDOWS_CHANGED (w);
  4217. }
  4218.          
  4219.  
  4220. /************************************************************************/
  4221. /*                         Window configurations                        */
  4222. /************************************************************************/
  4223.  
  4224. /* #### This window configuration stuff has had serious bugs lurking in it
  4225.    for years; it would be a -huge- win if this was reimplemented in lisp.
  4226.  */
  4227.  
  4228. /* If you add anything to this structure make sure saved_window_equal
  4229.    knows about it. */
  4230. struct saved_window
  4231. {
  4232.   Lisp_Object window;         /* window */
  4233.   Lisp_Object buffer;         /* buffer */
  4234.   Lisp_Object start;          /* copied marker */
  4235.   Lisp_Object pointm;         /* copied marker */
  4236.   Lisp_Object sb_point;          /* copied marker */
  4237.   Lisp_Object mark;           /* copied marker */
  4238.   int pixel_left;
  4239.   int pixel_top;
  4240.   int pixel_width;
  4241.   int pixel_height;
  4242.   int hscroll;
  4243.   int parent_index;           /* index into saved_windows */
  4244.   int prev_index;             /* index into saved_windows */
  4245.   Lisp_Object dedicated;
  4246.   char start_at_line_beg; /* boolean */
  4247. };
  4248.  
  4249. /* If you add anything to this structure make sure window_config_equal
  4250.    knows about it. */
  4251. struct window_config
  4252. {
  4253.   struct lcrecord_header header;
  4254.   int frame_width;
  4255.   int frame_height;
  4256. #if 0 /* FSFmacs */
  4257.   Lisp_Object selected_frame;
  4258. #endif
  4259.   Lisp_Object current_window;
  4260.   Lisp_Object current_buffer;
  4261.   Lisp_Object minibuf_scroll_window;
  4262.   Lisp_Object root_window;
  4263. #ifdef ENERGIZE
  4264.   /* The buffer whose p_sheets are visible */
  4265.   Lisp_Object p_sheet_buffer;
  4266. #endif
  4267.   int saved_windows_count;
  4268.   /* Zero-sized arrays aren't ANSI C */
  4269.   struct saved_window saved_windows[1];
  4270. };
  4271. #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
  4272.  
  4273. static Lisp_Object mark_window_config (Lisp_Object, void (*) (Lisp_Object));
  4274. static void print_window_config (Lisp_Object, Lisp_Object, int);
  4275. static unsigned int sizeof_window_config (CONST void *);
  4276.  
  4277. DECLARE_LRECORD (window_configuration, struct window_config);
  4278. #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
  4279. #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
  4280. #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
  4281. #define CHECK_WINDOW_CONFIGURATION(x, i) CHECK_RECORD (x, window_configuration)
  4282.  
  4283. DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
  4284.                     window_configuration,
  4285.                     mark_window_config,
  4286.                     print_window_config, 
  4287.                     0, 0, 0, sizeof_window_config,
  4288.                     struct window_config);
  4289.  
  4290. static Lisp_Object
  4291. mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
  4292. {
  4293.   struct window_config *config = XWINDOW_CONFIGURATION (obj);
  4294.   int i;
  4295.   ((markobj) (config->current_window));
  4296.   ((markobj) (config->current_buffer));
  4297.   ((markobj) (config->minibuf_scroll_window));
  4298.   ((markobj) (config->root_window));
  4299. #ifdef ENERGIZE
  4300.   ((markobj) (config->p_sheet_buffer));
  4301. #endif
  4302.   for (i = 0; i < config->saved_windows_count; i++)
  4303.     {
  4304.       struct saved_window *s = SAVED_WINDOW_N (config, i);
  4305.       ((markobj) (s->window));
  4306.       ((markobj) (s->buffer));
  4307.       ((markobj) (s->start));
  4308.       ((markobj) (s->pointm));
  4309.       ((markobj) (s->sb_point));
  4310.       ((markobj) (s->mark));
  4311.       ((markobj) (s->dedicated));
  4312.     }
  4313.   return (Qnil);
  4314. }
  4315.   
  4316. static unsigned int
  4317. sizeof_window_config (CONST void *h)
  4318. {
  4319.   CONST struct window_config *c = h;
  4320.   return (sizeof (*c)
  4321.           + ((c->saved_windows_count - 1) * sizeof (struct saved_window)));
  4322. }
  4323.  
  4324. static void
  4325. print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
  4326. {
  4327.   struct window_config *config = XWINDOW_CONFIGURATION (obj);
  4328.   char buf[200];
  4329.   if (print_readably)
  4330.     error ("printing unreadable object #<window-configuration 0x%x>",
  4331.            config->header.uid);
  4332.   write_c_string ("#<window-configuration ", printcharfun);
  4333.   sprintf (buf, "0x%x>", config->header.uid);
  4334.   write_c_string (buf, printcharfun);
  4335. }
  4336.  
  4337. /* Stolen from marker.c.  The saved windows store copies of the
  4338.    markers so we can't just do an EQ test. */
  4339. static int
  4340. window_marker_equal (Lisp_Object o1, Lisp_Object o2)
  4341. {
  4342.   if (EQ (o1, o2))
  4343.     return 1;
  4344.  
  4345.   if (!MARKERP (o1) || !MARKERP (o2))
  4346.     return 0;
  4347.  
  4348.   if (XMARKER (o1)->buffer != XMARKER (o2)->buffer)
  4349.     return 0;
  4350.   else if (!XMARKER (o1)->buffer)
  4351.     /* All markers pointing nowhere are equal */
  4352.     return 1;
  4353.   else
  4354.     return ((XMARKER (o1)->memind == XMARKER (o2)->memind));
  4355. }
  4356.  
  4357. /* Returns a boolean indicating whether the two saved windows are
  4358.    identical. */
  4359. static int
  4360. saved_window_equal (struct saved_window *win1, struct saved_window *win2)
  4361. {
  4362.   if (!EQ (win1->window, win2->window))
  4363.     return 0;
  4364.   else if (!EQ (win1->buffer, win2->buffer))
  4365.     return 0;
  4366.   else if (!window_marker_equal (win1->start, win2->start))
  4367.     return 0;
  4368.   else if (!window_marker_equal (win1->pointm, win2->pointm))
  4369.     return 0;
  4370.   else if (!window_marker_equal (win1->sb_point, win2->sb_point))
  4371.     return 0;
  4372.   else if (!window_marker_equal (win1->mark, win2->mark))
  4373.     return 0;
  4374.   else if (win1->pixel_left != win2->pixel_left)
  4375.     return 0;
  4376.   else if (win1->pixel_top != win2->pixel_top)
  4377.     return 0;
  4378.   else if (win1->pixel_width != win2->pixel_width)
  4379.     return 0;
  4380.   else if (win1->pixel_height != win2->pixel_height)
  4381.     return 0;
  4382.   else if (win1->hscroll != win2->hscroll)
  4383.     return 0;
  4384.   else if (win1->parent_index != win2->parent_index)
  4385.     return 0;
  4386.   else if (win1->prev_index != win2->prev_index)
  4387.     return 0;
  4388.   else if (!EQ (win1->dedicated, win2->dedicated))
  4389.     return 0;
  4390.   else if (win1->start_at_line_beg != win2->start_at_line_beg)
  4391.     return 0;
  4392.  
  4393.   return 1;
  4394. }
  4395.  
  4396. /* Returns a boolean indicating whether the two given configurations
  4397.    are identical. */
  4398. static int
  4399. window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
  4400. {
  4401.   struct window_config *fig1, *fig2;
  4402.   int i;
  4403.  
  4404.   /* First check if they are truly the same. */
  4405.   if (EQ (conf1, conf2))
  4406.     return 1;
  4407.  
  4408.   fig1 = XWINDOW_CONFIGURATION (conf1);
  4409.   fig2 = XWINDOW_CONFIGURATION (conf2);
  4410.  
  4411.   if (fig1->saved_windows_count != fig2->saved_windows_count)
  4412.     return 0;
  4413.   else if (!EQ (fig1->current_window, fig2->current_window))
  4414.     return 0;
  4415.   else if (!EQ (fig1->current_buffer, fig2->current_buffer))
  4416.     return 0;
  4417.   else if (!EQ (fig1->root_window, fig2->root_window))
  4418.     return 0;
  4419.   else if (!EQ (fig1->minibuf_scroll_window, fig2->minibuf_scroll_window))
  4420.     return 0;
  4421.   else if (fig1->frame_width != fig2->frame_width)
  4422.     return 0;
  4423.   else if (fig1->frame_height != fig2->frame_height)
  4424.     return 0;
  4425. #ifdef ENERGIZE
  4426.   else if (!EQ (fig1->p_sheet_buffer, fig2->p_sheet_buffer))
  4427.     return 0;
  4428. #endif
  4429.  
  4430.   for (i = 0; i < fig1->saved_windows_count; i++)
  4431.     {
  4432.       if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
  4433.                    SAVED_WINDOW_N (fig2, i)))
  4434.     return 0;
  4435.     }
  4436.  
  4437.   return 1;
  4438. }
  4439.  
  4440. DEFUN ("window-configuration-p", Fwindow_configuration_p,
  4441.        Swindow_configuration_p, 1, 1, 0,
  4442.   "T if OBJECT is a window-configuration object.")
  4443.   (obj)
  4444.      Lisp_Object obj;
  4445. {
  4446.   return (WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil);
  4447. }
  4448.  
  4449. /*
  4450.  * There are getting to be a lot of functions which traverse the
  4451.  * window structure doing various things.  It may be worth writing a
  4452.  * generic map-windows function.
  4453.  * #### I just did.  Feel free to rewrite. --ben
  4454.  */
  4455. void
  4456. mark_windows_in_use (Lisp_Object window, int mark)
  4457. {
  4458.   for (; !NILP (window) ; window = XWINDOW (window)->next)
  4459.     {
  4460.       XWINDOW (window)->config_mark = mark;
  4461.  
  4462.       if (!NILP (XWINDOW (window)->vchild))
  4463.     mark_windows_in_use (XWINDOW (window)->vchild, mark);
  4464.       else if (!NILP (XWINDOW (window)->hchild))
  4465.     mark_windows_in_use (XWINDOW (window)->hchild, mark);
  4466.     }
  4467. }
  4468.  
  4469. DEFUN ("set-window-configuration",
  4470.        Fset_window_configuration, Sset_window_configuration,
  4471.        1, 1, 0,
  4472.   "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
  4473. CONFIGURATION must be a value previously returned\n\
  4474. by `current-window-configuration' (which see).")
  4475.      (configuration)
  4476.      Lisp_Object configuration;
  4477. {
  4478.   struct window *w;
  4479.   struct window_config *config;
  4480.   struct saved_window *p;
  4481.   Lisp_Object new_current_buffer;
  4482.   int k;
  4483.   Lisp_Object frame;
  4484.   struct frame *f;
  4485.   struct gcpro gcpro1;
  4486.   Lisp_Object old_window_config;
  4487.   int previous_frame_height;
  4488.   int previous_frame_width;
  4489.  
  4490.   GCPRO1 (configuration);
  4491.  
  4492.   CHECK_WINDOW_CONFIGURATION (configuration, 0);
  4493.   config = XWINDOW_CONFIGURATION (configuration);
  4494.  
  4495.   frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
  4496.   f = XFRAME (frame);
  4497.  
  4498.   /* If the frame was deleted you can't restore the windows as they
  4499.      were deleted too.  Raise an error.  */
  4500.   if (!FRAME_LIVE_P (f))
  4501.     error ("Cannot set-window-configuration for a deleted frame");
  4502.  
  4503.     /* restore the frame characteristics */
  4504. #ifdef ENERGIZE
  4505.   if (FRAME_IS_X (f))
  4506.     {
  4507.       Lisp_Object new_desired = config->p_sheet_buffer;
  4508.     
  4509.       if (BUFFERP (new_desired) &&
  4510.       !BUFFER_LIVE_P (XBUFFER (new_desired)))
  4511.     new_desired = Qnil;    /* the desired buffer was killed */
  4512.     
  4513.       /* need to restore the desired buffer */
  4514.       if (!EQ (new_desired, desired_psheet_buffer (f)))
  4515.     make_psheets_desired (f, new_desired);
  4516.     }
  4517. #endif
  4518.     
  4519.   new_current_buffer = config->current_buffer;
  4520.   if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
  4521.     new_current_buffer = Qnil;
  4522.  
  4523.   /*
  4524.    * Assumed precondition:  w->config_mark = 0 for all w
  4525.    * This procedure should ensure this is true by the time it exits
  4526.    * to ensure the precondition for future calls.
  4527.    *
  4528.    * We use w->config_mark to know whether we're modifying a
  4529.    * window that is currently visible on the frame (#### we
  4530.    * should just be able to check whether the window is dead
  4531.    * or not, but this way is safer?).  As we process each
  4532.    * window, we set its config_mark to 0.  At the end, we
  4533.    * go through all the windows that used to be on the frame,
  4534.    * set each one's config_mark to 0 (to maintain the
  4535.    * assumed precondition) and delete each one that's no
  4536.    * longer in use.
  4537.    *
  4538.    * #### Using a window-configuration to keep track of
  4539.    * the current windows is wasteful.  All we need is the
  4540.    * list of windows, so we could just use a dynarr.
  4541.    */
  4542.   old_window_config = Fcurrent_window_configuration (frame);
  4543.  
  4544.   /* If the new configuration is already equal to the old, then stop
  4545.      right here.  This saves the work below and it also saves
  4546.      triggering a full redisplay of this window.  This is a huge win
  4547.      when using the mouse since the mode motion code uses
  4548.      save-window-excursion extensively but will rarely cause the
  4549.      configuration to actually change. */
  4550.   if (window_config_equal (configuration, old_window_config))
  4551.     {
  4552.       UNGCPRO;
  4553.       return Qnil;
  4554.     }
  4555.  
  4556.   mark_windows_in_use (f->root_window, 1);
  4557.  
  4558.   previous_frame_width = FRAME_WIDTH (f);
  4559.   previous_frame_height = FRAME_HEIGHT (f);
  4560.   /* If the frame has been resized since this window configuration was
  4561.      made, we change the frame to the size specified in the
  4562.      configuration, restore the configuration, and then resize it
  4563.      back.  We keep track of the prevailing height in these variables.  */
  4564.   if (config->frame_height != FRAME_HEIGHT (f)
  4565.       || config->frame_width != FRAME_WIDTH (f))
  4566.     change_frame_size (f, config->frame_height, config->frame_width, 0, 0);
  4567.  
  4568.   /* OK, now restore all the windows in the window config.
  4569.      This may involve "undeleting" windows, since the
  4570.      windows in the window config may be deleted.
  4571.      */
  4572.   for (k = 0; k < config->saved_windows_count; k++)
  4573.     {
  4574.       p = SAVED_WINDOW_N (config, k);
  4575.       w = XWINDOW (p->window);
  4576.       w->next = Qnil;
  4577.  
  4578.       /* The window might be dead.  In this case, its redisplay
  4579.      structures were freed, so we need to reallocate them. */
  4580.       if (!w->face_cache_elements)
  4581.     {
  4582.       w->face_cache_elements = Dynarr_new (struct face_cache_element);
  4583.       reset_face_cache_elements (w);
  4584.     }
  4585.       if (!w->glyph_cache_elements)
  4586.     w->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
  4587.       if (!w->line_start_cache)
  4588.     w->line_start_cache = Dynarr_new (struct line_start_cache);
  4589.       w->dead = 0;
  4590.  
  4591.       if (p->parent_index >= 0)
  4592.     w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
  4593.       else
  4594.     w->parent = Qnil;
  4595.  
  4596.       if (p->prev_index >= 0)
  4597.     {
  4598.       w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
  4599.  
  4600.       /* This is true for a minibuffer-only frame. */
  4601.       if (!NILP (w->mini_p) && EQ (w->prev, p->window))
  4602.         w->next = Qnil;
  4603.       else
  4604.         XWINDOW (w->prev)->next = p->window;
  4605.     }
  4606.       else
  4607.     {
  4608.       w->prev = Qnil;
  4609.       if (!NILP (w->parent))
  4610.         {
  4611.           if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
  4612.         {
  4613.           XWINDOW (w->parent)->vchild = p->window;
  4614.           XWINDOW (w->parent)->hchild = Qnil;
  4615.         }
  4616.           else
  4617.         {
  4618.           XWINDOW (w->parent)->hchild = p->window;
  4619.           XWINDOW (w->parent)->vchild = Qnil;
  4620.         }
  4621.         }
  4622.     }
  4623.       if (!w->config_mark)
  4624.     {
  4625.       /* #### This should be equivalent to the window previously
  4626.          having been dead.  If we're brave, we'll put in an
  4627.          assertion to this effect. */
  4628.       MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
  4629.     }
  4630.       else /* if (!EQ (w->buffer, p->buffer)) */
  4631.     {
  4632.       /* With the new redisplay we let it know that a change has
  4633.              been made and it will take care of the rest.  If we don't
  4634.              tell it something has possibly changed it could lead to
  4635.              incorrect display. */
  4636.       MARK_WINDOWS_CHANGED (w);
  4637.     }
  4638.  
  4639.       WINDOW_LEFT (w) = WINDOW_LEFT (p);
  4640.       WINDOW_TOP (w) = WINDOW_TOP (p);
  4641.       WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
  4642.       WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
  4643.       w->hscroll = p->hscroll;
  4644.       /* #### Here we need to restore the saved specs for
  4645.      has-modeline-p, scrollbar-width, scrollbar-height,
  4646.      modeline-shadow-thickness, left-margin-width,
  4647.      right-margin-width, and current-display-table. */
  4648.       w->dedicated = p->dedicated;
  4649.       w->line_cache_last_updated = Qzero;
  4650.       SET_LAST_MODIFIED (w, 1);
  4651.       SET_LAST_FACECHANGE (w);
  4652.       w->config_mark = 0;
  4653.  
  4654.       /* Reinstall the saved buffer and pointers into it.  */
  4655.       if (NILP (p->buffer))
  4656.     w->buffer = p->buffer;
  4657.       else
  4658.     {
  4659.       if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
  4660.         /* If saved buffer is alive, install it.  */
  4661.         {
  4662.           w->buffer = p->buffer;
  4663.           w->start_at_line_beg = p->start_at_line_beg;
  4664.           set_marker_restricted (w->start[CURRENT_DISP],
  4665.                           Fmarker_position (p->start),
  4666.                           w->buffer);
  4667.           set_marker_restricted (w->pointm[CURRENT_DISP],
  4668.                      Fmarker_position (p->pointm), w->buffer);
  4669.           set_marker_restricted (w->sb_point,
  4670.                      Fmarker_position (p->sb_point),
  4671.                      w->buffer);
  4672.           Fset_marker (XBUFFER (w->buffer)->mark,
  4673.                Fmarker_position (p->mark), w->buffer);
  4674.  
  4675.               /* As documented in Fcurrent_window_configuration, don't
  4676.                  save the location of point in the buffer which was current
  4677.                  when the window configuration was recorded.  */
  4678.           if (!EQ (p->buffer, new_current_buffer) &&
  4679.           XBUFFER (p->buffer) == current_buffer)
  4680.         Fgoto_char (w->pointm[CURRENT_DISP], Fcurrent_buffer ());
  4681.         }
  4682.       else if (NILP (w->buffer) || !BUFFER_LIVE_P (XBUFFER (w->buffer)))
  4683.         /* Else if window's old buffer is dead too, get a live one.  */
  4684.         {
  4685.           /* #### The following line makes me nervous... */
  4686.            /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
  4687.           w->buffer = Fget_buffer_create (QSscratch);
  4688.            /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
  4689.           /* This will set the markers to beginning of visible range.  */
  4690.           set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
  4691.           set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
  4692.                      w->buffer);
  4693.           set_marker_restricted (w->sb_point, Qzero, w->buffer);
  4694.           w->start_at_line_beg = 1;
  4695.         }
  4696.       else
  4697.         /* Keeping window's old buffer; make sure the markers are real.  */
  4698.         {
  4699.           /* Set window markers at start of visible range.  */
  4700.           if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
  4701.         set_marker_restricted (w->start[CURRENT_DISP], Qzero,
  4702.                        w->buffer);
  4703.           if (XMARKER (w->sb_point)->buffer == 0)
  4704.         set_marker_restricted (w->sb_point, Qzero, w->buffer);
  4705.           if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
  4706.         set_marker_restricted (w->pointm[CURRENT_DISP],
  4707.                        make_number
  4708.                        (BUF_PT (XBUFFER (w->buffer))),
  4709.                        w->buffer);
  4710.           w->start_at_line_beg = 1;
  4711.         }
  4712.       /* We just potentially changed the window's buffer and
  4713.          potentially turned a dead window into a live one,
  4714.          so we need to recompute the cached specifier values. */
  4715.       recompute_all_cached_specifiers_in_window (w);
  4716.     }
  4717.     }
  4718.  
  4719.   FRAME_ROOT_WINDOW (f) = config->root_window;
  4720.  
  4721. #if 0 /* FSFmacs */
  4722.   if (NILP (config->focus_frame)
  4723.       || (FRAMEP (config->focus_frame)
  4724.       && FRAME_LIVE_P (XFRAME (config->focus_frame))))
  4725.     Fredirect_frame_focus (frame, config->focus_frame);
  4726. #endif
  4727.   
  4728.   /* Set the frame height to the value it had before this function.  */
  4729.   if (previous_frame_height != FRAME_HEIGHT (f)
  4730.       || previous_frame_width != FRAME_WIDTH (f))
  4731.     change_frame_size (f, previous_frame_height, previous_frame_width,
  4732.                0, 0);
  4733.  
  4734.    /* If restoring in the current frame make the window current, otherwise
  4735.       just update the frame selected_window slot to be the restored
  4736.       current_window. */
  4737.   if (f == selected_frame ())
  4738.     {
  4739.       Fselect_window (config->current_window);
  4740.       if (!NILP (new_current_buffer))
  4741.     Fset_buffer (new_current_buffer);
  4742.       else
  4743.     Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
  4744. #ifdef ENERGIZE
  4745.       energize_buffer_shown_hook (XWINDOW (Fselected_window (Qnil)));
  4746. #endif
  4747.     }
  4748.   else
  4749.     f->selected_window = config->current_window;
  4750.  
  4751. #if 0 /* FSFmacs */
  4752.   /* Fselect_window will have made f the selected frame, so we
  4753.      reselect the proper frame here.  Fhandle_switch_frame will change the
  4754.      selected window too, but that doesn't make the call to
  4755.      Fselect_window above totally superfluous; it still sets f's
  4756.      selected window.  */
  4757.   if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
  4758.     Fhandle_switch_frame (config->selected_frame, Qnil);
  4759. #endif
  4760.  
  4761.   Vminibuf_scroll_window = config->minibuf_scroll_window;
  4762.  
  4763.   config = XWINDOW_CONFIGURATION (old_window_config);
  4764.   for (k = 0; k < config->saved_windows_count; k++)
  4765.     {
  4766.       p = SAVED_WINDOW_N (config, k);
  4767.       w = XWINDOW (p->window);
  4768.       /* Remember, we set w->config_mark on all currently visible
  4769.      windows, and reset it on all newly visible windows.
  4770.      Any windows still marked need to be deleted. */
  4771.       if (w->config_mark)
  4772.     {
  4773.       mark_window_as_deleted (w);
  4774.       w->config_mark = 0;
  4775.     }
  4776.     }
  4777.  
  4778.   UNGCPRO;
  4779.  
  4780.   f->mirror_dirty = 1;
  4781.  
  4782.   return (Qnil);
  4783. }
  4784.  
  4785. /* Mark all subwindows of a window as deleted.  The argument
  4786.    W is actually the subwindow tree of the window in question. */
  4787.  
  4788. void
  4789. delete_all_subwindows (struct window *w)
  4790. {
  4791.   if (!NILP (w->next))
  4792.     delete_all_subwindows (XWINDOW (w->next));
  4793.   if (!NILP (w->vchild))
  4794.     delete_all_subwindows (XWINDOW (w->vchild));
  4795.   if (!NILP (w->hchild))
  4796.     delete_all_subwindows (XWINDOW (w->hchild));
  4797.  
  4798.   mark_window_as_deleted (w);
  4799. }
  4800.  
  4801.  
  4802. static int
  4803. count_windows (struct window *window)
  4804. {
  4805.   int count = 1;
  4806.   if (!NILP (window->next))
  4807.     count += count_windows (XWINDOW (window->next));
  4808.   if (!NILP (window->vchild))
  4809.     count += count_windows (XWINDOW (window->vchild));
  4810.   if (!NILP (window->hchild))
  4811.     count += count_windows (XWINDOW (window->hchild));
  4812.   return count;
  4813. }
  4814.  
  4815. static int
  4816. saved_window_index (Lisp_Object window, struct window_config *config, int lim)
  4817. {
  4818.   int j;
  4819.   for (j = 0; j < lim; j++)
  4820.   {
  4821.     if (EQ (SAVED_WINDOW_N (config, j)->window, window))
  4822.     {
  4823.       return (j);
  4824.     }
  4825.   }
  4826.   abort ();
  4827.   return 0;    /* suppress compiler warning */
  4828. }
  4829.  
  4830. static int
  4831. save_window_save (Lisp_Object window, struct window_config *config, int i)
  4832. {
  4833.   struct saved_window *p;
  4834.   struct window *w;
  4835.  
  4836.   for (; !NILP (window); window = w->next)
  4837.     {
  4838.       p = SAVED_WINDOW_N (config, i);
  4839.       w = XWINDOW (window);
  4840.  
  4841.       i++;
  4842.       p->window = window;
  4843.       p->buffer = w->buffer;
  4844.       WINDOW_LEFT (p) = WINDOW_LEFT (w);
  4845.       WINDOW_TOP (p) = WINDOW_TOP (w);
  4846.       WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
  4847.       WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
  4848.       p->hscroll = w->hscroll;
  4849.       /* #### Here we need to save the specs for
  4850.      has-modeline-p, scrollbar-width, scrollbar-height,
  4851.      modeline-shadow-thickness, left-margin-width,
  4852.      right-margin-width, and current-display-table. */
  4853.       if (!NILP (w->buffer))
  4854.     {
  4855.       /* Save w's value of point in the window configuration.
  4856.          If w is the selected window, then get the value of point
  4857.          from the buffer; pointm is garbage in the selected window.  */
  4858.       if (EQ (window, Fselected_window (Qnil)))
  4859.         {
  4860.           p->pointm = Fmake_marker ();
  4861.           Fset_marker (p->pointm,
  4862.                make_number (BUF_PT (XBUFFER (w->buffer))),
  4863.                w->buffer);
  4864.         }
  4865.       else
  4866.         p->pointm = Fcopy_marker (w->pointm[CURRENT_DISP]);
  4867.  
  4868.       p->start = Fcopy_marker (w->start[CURRENT_DISP]);
  4869.       p->sb_point = Fcopy_marker (w->sb_point);
  4870.       p->start_at_line_beg = w->start_at_line_beg;
  4871.  
  4872.       p->mark = Fcopy_marker (XBUFFER (w->buffer)->mark);
  4873.     }
  4874.       else
  4875.     {
  4876.       p->pointm = Qnil;
  4877.       p->start = Qnil;
  4878.       p->sb_point = Qnil;
  4879.       p->mark = Qnil;
  4880.       p->start_at_line_beg = 0;
  4881.     }
  4882.  
  4883.       if (NILP (w->parent))
  4884.     p->parent_index = -1;
  4885.       else
  4886.         p->parent_index = saved_window_index (w->parent, config, i);
  4887.       if (NILP (w->prev))
  4888.     p->prev_index = -1;
  4889.       else
  4890.         p->prev_index = saved_window_index (w->prev, config, i);
  4891.       p->dedicated = w->dedicated;
  4892.       if (!NILP (w->vchild))
  4893.     i = save_window_save (w->vchild, config, i);
  4894.       if (!NILP (w->hchild))
  4895.     i = save_window_save (w->hchild, config, i);
  4896.     }
  4897.  
  4898.   return i;
  4899. }
  4900.  
  4901. #if 0 /* FSFmacs */
  4902. /* Added to doc string:
  4903.  
  4904. This also records the currently selected frame, and FRAME's focus\n\
  4905. redirection (see `redirect-frame-focus').
  4906.  
  4907. */
  4908. #endif
  4909.  
  4910. DEFUN ("current-window-configuration",
  4911.     Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
  4912.   "Return an object representing the current window configuration of FRAME.\n\
  4913. If FRAME is nil or omitted, use the selected frame.\n\
  4914. This describes the number of windows, their sizes and current buffers,\n\
  4915. and for each displayed buffer, where display starts, and the positions of\n\
  4916. point and mark.  An exception is made for point in the current buffer:\n\
  4917. its value is -not- saved.")
  4918.   (frame)
  4919.      Lisp_Object frame;
  4920. {
  4921.   Lisp_Object result = Qnil;
  4922.   struct frame *f;
  4923.   int n_windows;
  4924.  
  4925.   struct window_config *config;
  4926.  
  4927.   f = get_frame (frame);
  4928.  
  4929.   n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
  4930.   config = alloc_lcrecord ((int) ((sizeof (struct window_config)
  4931.                    /* n_windows - 1 because zero-sized arrays
  4932.                     *  aren't ANSI C */
  4933.                    + ((n_windows - 1)
  4934.                       * sizeof (struct saved_window)))),
  4935.                   lrecord_window_configuration);
  4936.   XSETWINDOW_CONFIGURATION (result, config);
  4937.  
  4938.   config->frame_width = FRAME_WIDTH (f);
  4939.   config->frame_height = FRAME_HEIGHT (f);
  4940.   config->current_window = FRAME_SELECTED_WINDOW (f);
  4941.   XSETBUFFER (config->current_buffer, current_buffer);
  4942.   config->minibuf_scroll_window = Vminibuf_scroll_window;
  4943.   config->root_window = FRAME_ROOT_WINDOW (f);
  4944.   config->saved_windows_count = n_windows;
  4945. #ifdef ENERGIZE
  4946.   {
  4947.     config->p_sheet_buffer = desired_psheet_buffer (f);
  4948.     if (EQ (config->p_sheet_buffer, Qzero)) /* #### necessaryp? */
  4949.       config->p_sheet_buffer = Qnil;
  4950.   }
  4951. #endif
  4952.   save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
  4953.   return (result);
  4954. }
  4955.  
  4956. DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
  4957.   0, UNEVALLED, 0,
  4958.   "Execute body, preserving window sizes and contents.\n\
  4959. Restores which buffer appears in which window, where display starts,\n\
  4960. as well as the current buffer.\n\
  4961. Does not restore the value of point in current buffer.")
  4962.   (args)
  4963.      Lisp_Object args;
  4964. {
  4965.   /* This function can GC */
  4966.   Lisp_Object val;
  4967.   int speccount = specpdl_depth ();
  4968.  
  4969.   record_unwind_protect (Fset_window_configuration,
  4970.              Fcurrent_window_configuration (Qnil));
  4971.   val = Fprogn (args);
  4972.   return unbind_to (speccount, val);
  4973. }
  4974.  
  4975.  
  4976. /************************************************************************/
  4977. /*                            initialization                            */
  4978. /************************************************************************/
  4979.  
  4980. void
  4981. syms_of_window (void)
  4982. {
  4983.   defsymbol (&Qwindowp, "windowp");
  4984.   defsymbol (&Qwindow_live_p, "window-live-p");
  4985.   defsymbol (&Qwindow_configurationp, "window-configuration-p");
  4986.   defsymbol (&Qscroll_up, "scroll-up");
  4987.   defsymbol (&Qscroll_down, "scroll-down");
  4988.   defsymbol (&Qvisible, "visible");
  4989.  
  4990.   defsubr (&Sselected_window);
  4991.   defsubr (&Sminibuffer_window);
  4992.   defsubr (&Swindow_minibuffer_p);
  4993.   defsubr (&Swindowp);
  4994.   defsubr (&Swindow_live_p);
  4995.   defsubr (&Swindow_lowest_p);
  4996.   defsubr (&Swindow_highest_p);
  4997.   defsubr (&Spos_visible_in_window_p);
  4998.   defsubr (&Swindow_buffer);
  4999.   defsubr (&Swindow_frame);
  5000.   defsubr (&Swindow_height);
  5001.   defsubr (&Swindow_width);
  5002.   defsubr (&Swindow_pixel_height);
  5003.   defsubr (&Swindow_pixel_width);
  5004.   defsubr (&Swindow_hscroll);
  5005.   defsubr (&Sset_window_hscroll);
  5006.   defsubr (&Swindow_pixel_edges);
  5007.   defsubr (&Swindow_point);
  5008.   defsubr (&Swindow_start);
  5009.   defsubr (&Swindow_end);
  5010.   defsubr (&Sset_window_point);
  5011.   defsubr (&Sset_window_start);
  5012.   defsubr (&Swindow_dedicated_p);
  5013.   defsubr (&Sset_window_buffer_dedicated);
  5014.   defsubr (&Snext_window);
  5015.   defsubr (&Sprevious_window);
  5016.   defsubr (&Snext_vertical_window);
  5017.   defsubr (&Sother_window);
  5018.   defsubr (&Sget_lru_window);
  5019.   defsubr (&Sget_largest_window);
  5020.   defsubr (&Sget_buffer_window);
  5021.   defsubr (&Swindow_left_margin_pixel_width);
  5022.   defsubr (&Swindow_right_margin_pixel_width);
  5023.   defsubr (&Sdelete_other_windows);
  5024.   defsubr (&Sdelete_windows_on);
  5025.   defsubr (&Sreplace_buffer_in_windows);
  5026.   defsubr (&Sdelete_window);
  5027.   defsubr (&Sset_window_buffer);
  5028.   defsubr (&Sselect_window);
  5029.   defsubr (&Sdisplay_buffer);
  5030.   defsubr (&Ssplit_window);
  5031.   defsubr (&Senlarge_window);
  5032.   defsubr (&Sshrink_window);
  5033.   defsubr (&Sscroll_up);
  5034.   defsubr (&Sscroll_down);
  5035.   defsubr (&Sscroll_left);
  5036.   defsubr (&Sscroll_right);
  5037.   defsubr (&Sother_window_for_scrolling);
  5038.   defsubr (&Sscroll_other_window);
  5039.   defsubr (&Srecenter);
  5040.   defsubr (&Smove_to_window_line);
  5041.   defsubr (&Swindow_configuration_p);
  5042.   defsubr (&Sset_window_configuration);
  5043.   defsubr (&Scurrent_window_configuration);
  5044.   defsubr (&Ssave_window_excursion);
  5045. }
  5046.  
  5047. void
  5048. vars_of_window (void)
  5049. {
  5050.   /* Make sure all windows get marked */
  5051.   minibuf_window = Qnil;
  5052.   staticpro (&minibuf_window);
  5053.  
  5054.   DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines,
  5055.     "*Non-nil means to scroll if point lands on a line which is clipped.");
  5056.   scroll_on_clipped_lines = 1;
  5057.  
  5058.   DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
  5059.     "Non-nil means call as function to display a help buffer.\n\
  5060. Used by `with-output-to-temp-buffer'.");
  5061.   Vtemp_buffer_show_function = Qnil;
  5062.  
  5063.   DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
  5064.     "If non-nil, function to call to handle `display-buffer'.\n\
  5065. It will receive three args: the same as those to `display-buffer'.");
  5066.   Vdisplay_buffer_function = Qnil;
  5067.  
  5068.   DEFVAR_LISP ("pre-display-buffer-function", &Vpre_display_buffer_function,
  5069.     "If non-nil, function that will be called from `display-buffer'\n\
  5070. as the first action.  It will receive three args: the same as those\n\
  5071. to `display-buffer'.\n\
  5072. This function may be used to select an appropriate frame for the buffer,\n\
  5073. for example.  See also the variable `display-buffer-function', which may\n\
  5074. be used to completely replace the `display-buffer' function.");
  5075.   Vpre_display_buffer_function = Qnil;
  5076.  
  5077.   DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
  5078.     "Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.");
  5079.   Vminibuf_scroll_window = Qnil;
  5080.  
  5081.   DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
  5082.     "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
  5083.   Vother_window_scroll_buffer = Qnil;
  5084.  
  5085. #if 0 /* FSFmacs */
  5086.   xxDEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
  5087.     "*Non-nil means `display-buffer' should make a separate frame.");
  5088.   pop_up_frames = 0;
  5089.  
  5090.   xxDEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
  5091.     "Function to call to handle automatic new frame creation.\n\
  5092. It is called with no arguments and should return a newly created frame.\n\
  5093. \n\
  5094. A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
  5095. where `pop-up-frame-alist' would hold the default frame parameters.");
  5096.   Vpop_up_frame_function = Qnil;
  5097.  
  5098.   xxDEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
  5099.     "*List of buffer names that should have their own special frames.\n\
  5100. Displaying a buffer whose name is in this list makes a special frame for it\n\
  5101. using `special-display-function'.  See also `special-display-regexps'.");
  5102.   Vspecial_display_buffer_names = Qnil;
  5103.  
  5104.   xxDEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
  5105.     "*List of regexps saying which buffers should have their own special frames.\n\
  5106. If a buffer name matches one of these regexps, it gets its own frame.\n\
  5107. Displaying a buffer whose name is in this list makes a special frame for it\n\
  5108. using `special-display-function'.  See also `special-display-buffer-names'.");
  5109.   Vspecial_display_regexps = Qnil;
  5110.  
  5111.   xxDEFVAR_LISP ("special-display-function", &Vspecial_display_function,
  5112.     "Function to call to make a new frame for a special buffer.\n\
  5113. It is called with one argument, the buffer,\n\
  5114. and should return a window displaying that buffer.\n\
  5115. The default value makes a separate frame for the buffer,\n\
  5116. using `special-display-alist' to specify the frame parameters.\n\
  5117. \n\
  5118. A buffer is special if its is listed in `special-display-buffer-names'\n\
  5119. or matches a regexp in `special-display-regexps'.");
  5120.   Vspecial_display_function = Qnil;
  5121. #endif
  5122.  
  5123.   DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
  5124.     "*Non-nil means display-buffer should make new windows.");
  5125.   pop_up_windows = 1;
  5126.  
  5127.   DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
  5128.     "*Number of lines of continuity when scrolling by screenfuls.");
  5129.   next_screen_context_lines = 2;
  5130.  
  5131.   DEFVAR_INT ("split-height-threshold", &split_height_threshold,
  5132.     "*display-buffer would prefer to split the largest window if this large.\n\
  5133. If there is only one window, it is split regardless of this value.");
  5134.   split_height_threshold = 500;
  5135.  
  5136.   DEFVAR_INT ("split-width-threshold", &split_width_threshold,
  5137.     "*display-buffer would prefer to split the largest window if this large.\n\
  5138. If there is only one window, it is split regardless of this value.");
  5139.   split_width_threshold = 500;
  5140.  
  5141.   DEFVAR_INT ("window-min-height", &window_min_height,
  5142.     "*Delete any window less than this tall (including its modeline).");
  5143.   window_min_height = 4;
  5144.  
  5145.   DEFVAR_INT ("window-min-width", &window_min_width,
  5146.     "*Delete any window less than this wide.");
  5147.   window_min_width = 10;
  5148. }
  5149.  
  5150. void
  5151. specifier_vars_of_window (void)
  5152. {
  5153.   DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness,
  5154.     "*How thick to draw 3D shadows around modelines.\n\
  5155. If this is set to 0, modelines will be the traditional 2D.  Sizes above\n\
  5156. 10 will be accepted but the maximum thickness that will be drawn is 10.\n\
  5157. This is a specifier; use `set-specifier' to change it.");
  5158.   Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
  5159.   /* The initial value for modeline-shadow-thickness is 2, but if the
  5160.      user removes all specifications we provide a fallback value of 0,
  5161.      which is probably what was expected. */
  5162.   set_specifier_fallback (Vmodeline_shadow_thickness,
  5163.               list1 (Fcons (Qnil, Qzero)));
  5164.   Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_number (2),
  5165.               Qnil, Qnil, Qnil);
  5166.   set_specifier_caching (Vmodeline_shadow_thickness,
  5167.              slot_offset (struct window,
  5168.                       modeline_shadow_thickness),
  5169.              modeline_shadow_thickness_changed,
  5170.              0, 0);
  5171.   
  5172.   DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p,
  5173.     "*Whether the modeline should be displayed.\n\
  5174. This is a specifier; use `set-specifier' to change it.");
  5175.   Vhas_modeline_p = Fmake_specifier (Qboolean);
  5176.   set_specifier_fallback (Vhas_modeline_p,
  5177.               list1 (Fcons (Qnil, Qt)));
  5178.   set_specifier_caching (Vhas_modeline_p,
  5179.              slot_offset (struct window,
  5180.                       has_modeline_p),
  5181.              /* #### It's strange that we need a special
  5182.                 flag to indicate that the shadow-thickness
  5183.                 has changed, but not one to indicate that
  5184.                 the modeline has been turned off or on. */
  5185.              some_window_value_changed,
  5186.              0, 0);
  5187. }
  5188.